{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## The NumPy ndarray: A Multidimensional Array Object"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.38913362, -0.45430204, -0.57324232],\n",
       "       [ 0.02240496, -0.10517885, -1.55549342]])"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "# Generate some random data\n",
    "data = np.random.randn(2, 3)\n",
    "data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.77826724, -0.90860408, -1.14648464],\n",
       "       [ 0.04480991, -0.21035771, -3.11098685]])"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\n",
    "data + data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 2.59788254, -9.16349367,  2.63155473],\n",
       "       [-8.27524547,  8.43834816,  3.27301986]])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data * 10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dtype('float64')"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\n",
    "data.dtype"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2, 3)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Creating ndarrays"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([6. , 7.5, 8. , 0. , 1. ])"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#array函数接受一切序列型对象\n",
    "data1 = [6, 7.5, 8, 0, 1]\n",
    "arr1 = np.array(data1)\n",
    "arr1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3, 4],\n",
       "       [5, 6, 7, 8]])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data2 = [[1, 2, 3, 4], [5, 6, 7, 8]]\n",
    "arr2 = np.array(data2)\n",
    "arr2\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2, 4)"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2.ndim"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dtype('int32')"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2.dtype"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dtype('float64')"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr1.dtype"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.zeros(10)#zeros和ones分别可以创建指定长度或形状的全0或全1数组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0., 0., 0., 0., 0., 0.],\n",
       "       [0., 0., 0., 0., 0., 0.],\n",
       "       [0., 0., 0., 0., 0., 0.]])"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.zeros((3, 6))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[0., 0.],\n",
       "        [0., 0.],\n",
       "        [0., 0.]],\n",
       "\n",
       "       [[0., 0.],\n",
       "        [0., 0.],\n",
       "        [0., 0.]]])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.empty((2, 3, 2))#empty可以创建一个没有任何具体值得数组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.arange(15)#arange是Python内置函数range的数组版"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 0., 0.],\n",
       "       [0., 1., 0.],\n",
       "       [0., 0., 1.]])"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.eye(3)#eye和identity函数创建一个正方的N*N单位矩阵（对角线为1，其余为0）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 0., 0., 0., 0.],\n",
       "       [0., 1., 0., 0., 0.],\n",
       "       [0., 0., 1., 0., 0.],\n",
       "       [0., 0., 0., 1., 0.],\n",
       "       [0., 0., 0., 0., 1.]])"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.identity(5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Data Types for ndarrays"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "arr1 = np.array([1, 2, 3], dtype=np.float64)#类型名后面跟一个用于表示各元素位长的数字\n",
    "arr2 = np.array([1, 2, 3], dtype=np.int32)\n",
    "arr1.dtype\n",
    "arr2.dtype"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dtype('int32')"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.array([1, 2, 3, 4, 5])\n",
    "arr.dtype"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dtype('float64')"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "float_arr = arr.astype(np.float64)#通过ndarray的astype方法显式地转换其dtype\n",
    "float_arr.dtype"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1. 2. 3. 4. 5.]\n"
     ]
    }
   ],
   "source": [
    "print(float_arr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 3, -1, -2,  0, 12, 10])"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.array([3.7, -1.2, -2.6, 0.5, 12.9, 10.1])\n",
    "arr\n",
    "arr.astype(np.int32)#将浮点数转换成整数，小数部分会被截断"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 1.25, -9.6 , 42.  ])"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "numeric_strings = np.array(['1.25', '-9.6', '42'], dtype=np.string_)\n",
    "numeric_strings.astype(float)#如果某字符串数组全是数字，可以用astype将其转换成数值形式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "int_array = np.arange(10)\n",
    "calibers = np.array([.22, .270, .357, .380, .44, .50], dtype=np.float64)\n",
    "int_array.astype(calibers.dtype)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([         0, 1075314688,          0, 1075707904,          0,\n",
       "       1075838976,          0, 1072693248], dtype=uint32)"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "empty_uint32 = np.empty(8, dtype='u4')#可以用简洁的类型代码来表示dtype\n",
    "empty_uint32"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Arithmetic with NumPy Arrays"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1.,  4.,  9.],\n",
       "       [16., 25., 36.]])"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.array([[1., 2., 3.], [4., 5., 6.]])\n",
    "arr * arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0., 0., 0.],\n",
       "       [0., 0., 0.]])"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr - arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1.        , 0.5       , 0.33333333],\n",
       "       [0.25      , 0.2       , 0.16666667]])"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "1 / arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1.        , 1.41421356, 1.73205081],\n",
       "       [2.        , 2.23606798, 2.44948974]])"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr ** 0.5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[False,  True, False],\n",
       "       [ True, False,  True]])"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2 = np.array([[0., 4., 1.], [7., 2., 12.]])\n",
    "arr2 > arr"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Basic Indexing and Slicing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.arange(10)\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr[5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([5, 6, 7])"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr[5:8]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "arr[5:8] = 12#当将一个标量值赋值给一个切片时（如arr[5:8] = 12），该值会自动传播到整个选区"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0,  1,  2,  3,  4, 12, 12, 12,  8,  9])"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([12, 12, 12])"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr_slice = arr[5:8]#数组切片是原是数组的视图\n",
    "arr_slice"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([    0,     1,     2,     3,     4,    12, 12345,    12,     8,\n",
       "           9])"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr_slice[1] = 12345#视图上的任何修改都会直接反映到源数组上\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0,  1,  2,  3,  4, 64, 64, 64,  8,  9])"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr_slice[:] = 64\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([7, 8, 9])"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])\n",
    "arr2d[2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2d[0][2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2d[0, 2]#传入一个以逗号隔开的索引列表来选取单个元素，与arr2d[0][2]等价"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[ 1,  2,  3],\n",
       "        [ 4,  5,  6]],\n",
       "\n",
       "       [[ 7,  8,  9],\n",
       "        [10, 11, 12]]])"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr3d = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])\n",
    "arr3d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3],\n",
       "       [4, 5, 6]])"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr3d[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[42, 42, 42],\n",
       "        [42, 42, 42]],\n",
       "\n",
       "       [[ 7,  8,  9],\n",
       "        [10, 11, 12]]])"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "old_values = arr3d[0].copy()\n",
    "arr3d[0] = 42\n",
    "arr3d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[ 1,  2,  3],\n",
       "        [ 4,  5,  6]],\n",
       "\n",
       "       [[ 7,  8,  9],\n",
       "        [10, 11, 12]]])"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr3d[0] = old_values\n",
    "arr3d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([7, 8, 9])"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr3d[1, 0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 7,  8,  9],\n",
       "       [10, 11, 12]])"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = arr3d[1]\n",
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([7, 8, 9])"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Indexing with slices"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2, 3, 4, 5])"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr\n",
    "arr[1:6]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3],\n",
       "       [4, 5, 6],\n",
       "       [7, 8, 9]])"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3],\n",
       "       [4, 5, 6]])"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2d[:2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[2, 3],\n",
       "       [5, 6]])"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2d[:2, 1:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([4, 5])"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2d[1, :2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([3, 6])"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2d[:2, 2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1],\n",
       "       [4],\n",
       "       [7]])"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2d[:, :1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 0, 0],\n",
       "       [4, 0, 0],\n",
       "       [7, 8, 9]])"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2d[:2, 1:] = 0\n",
    "arr2d"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Boolean Indexing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [],
   "source": [
    "nams = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])\n",
    "data = np.random.randn(7, 4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'], dtype='<U4')"
      ]
     },
     "execution_count": 68,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "nams"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.61633527, -1.30067525,  0.79185806,  0.01865169],\n",
       "       [-0.83412121,  1.50258562, -0.34642068,  0.00963797],\n",
       "       [-2.29667163,  0.78264549, -1.33481402, -1.05895853],\n",
       "       [-0.44246026, -0.16952191,  0.88332947,  1.08209078],\n",
       "       [-0.43138741, -0.64037834,  0.7567488 ,  0.28870089],\n",
       "       [ 0.77173189, -1.87931721, -0.02966628, -0.01979843],\n",
       "       [ 0.79444887,  1.59317843,  1.79299736, -0.81493112]])"
      ]
     },
     "execution_count": 69,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ True, False, False,  True, False, False, False])"
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "nams == 'Bob'#跟算术运算一样，数组的比较运算（如==）也是矢量化的，因此对names和字符串'Bob'的比较运算将会产生一个布尔型数组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.61633527, -1.30067525,  0.79185806,  0.01865169],\n",
       "       [-0.44246026, -0.16952191,  0.88332947,  1.08209078]])"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data[nams == 'Bob']#选出对应于名字“Bob”的所有行，布尔型数组的长度必须跟被索引的轴长度一致"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.79185806, 0.01865169],\n",
       "       [0.88332947, 1.08209078]])"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data[nams == 'Bob', 2:]#将布尔数组跟切片、整数混合使用"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.01865169, 1.08209078])"
      ]
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data[nams == 'Bob', 3]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([False,  True,  True, False,  True,  True,  True])"
      ]
     },
     "execution_count": 78,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "nams != 'Bob'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.83412121,  1.50258562, -0.34642068,  0.00963797],\n",
       "       [-2.29667163,  0.78264549, -1.33481402, -1.05895853],\n",
       "       [-0.43138741, -0.64037834,  0.7567488 ,  0.28870089],\n",
       "       [ 0.77173189, -1.87931721, -0.02966628, -0.01979843],\n",
       "       [ 0.79444887,  1.59317843,  1.79299736, -0.81493112]])"
      ]
     },
     "execution_count": 81,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data[~(nams == 'Bob')]#选取除Bob以外的其他值，既可以使用不等号，也可以通过（~）对条件进行否定"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.83412121,  1.50258562, -0.34642068,  0.00963797],\n",
       "       [-2.29667163,  0.78264549, -1.33481402, -1.05895853],\n",
       "       [-0.43138741, -0.64037834,  0.7567488 ,  0.28870089],\n",
       "       [ 0.77173189, -1.87931721, -0.02966628, -0.01979843],\n",
       "       [ 0.79444887,  1.59317843,  1.79299736, -0.81493112]])"
      ]
     },
     "execution_count": 83,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cond = nams == 'Bob'\n",
    "data[~cond]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ True, False,  True,  True,  True, False, False])"
      ]
     },
     "execution_count": 84,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mask = (nams == 'Bob') | (nams == 'Will')#组合多个布尔条件，使用&（和）、|（或）\n",
    "mask"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.61633527, -1.30067525,  0.79185806,  0.01865169],\n",
       "       [-2.29667163,  0.78264549, -1.33481402, -1.05895853],\n",
       "       [-0.44246026, -0.16952191,  0.88332947,  1.08209078],\n",
       "       [-0.43138741, -0.64037834,  0.7567488 ,  0.28870089]])"
      ]
     },
     "execution_count": 85,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data[mask]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.61633527, 0.        , 0.79185806, 0.01865169],\n",
       "       [0.        , 1.50258562, 0.        , 0.00963797],\n",
       "       [0.        , 0.78264549, 0.        , 0.        ],\n",
       "       [0.        , 0.        , 0.88332947, 1.08209078],\n",
       "       [0.        , 0.        , 0.7567488 , 0.28870089],\n",
       "       [0.77173189, 0.        , 0.        , 0.        ],\n",
       "       [0.79444887, 1.59317843, 1.79299736, 0.        ]])"
      ]
     },
     "execution_count": 86,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data[data < 0] = 0#通过布尔数组设置值是一种经常用到的手段\n",
    "data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[7.        , 7.        , 7.        , 7.        ],\n",
       "       [0.        , 1.50258562, 0.        , 0.00963797],\n",
       "       [7.        , 7.        , 7.        , 7.        ],\n",
       "       [7.        , 7.        , 7.        , 7.        ],\n",
       "       [7.        , 7.        , 7.        , 7.        ],\n",
       "       [0.77173189, 0.        , 0.        , 0.        ],\n",
       "       [0.79444887, 1.59317843, 1.79299736, 0.        ]])"
      ]
     },
     "execution_count": 87,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data[nams != 'Joe'] = 7#通过布尔数组设置正行整列的值也很简单\n",
    "data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Fancy Indexing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0., 0., 0., 0.],\n",
       "       [1., 1., 1., 1.],\n",
       "       [2., 2., 2., 2.],\n",
       "       [3., 3., 3., 3.],\n",
       "       [4., 4., 4., 4.],\n",
       "       [5., 5., 5., 5.],\n",
       "       [6., 6., 6., 6.],\n",
       "       [7., 7., 7., 7.]])"
      ]
     },
     "execution_count": 88,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.empty((8, 4))\n",
    "for i in range(8):\n",
    "    arr[i] = i\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[4., 4., 4., 4.],\n",
       "       [3., 3., 3., 3.],\n",
       "       [0., 0., 0., 0.],\n",
       "       [6., 6., 6., 6.]])"
      ]
     },
     "execution_count": 89,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr[[4, 3, 0, 6]]#以特定顺序选取子集，只需传入一个用于指定顺序的整数列表或ndarray即可"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[5., 5., 5., 5.],\n",
       "       [3., 3., 3., 3.],\n",
       "       [1., 1., 1., 1.]])"
      ]
     },
     "execution_count": 90,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr[[-3, -5, -7]]#使用负数索引将会从末尾开始选取行"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  1,  2,  3],\n",
       "       [ 4,  5,  6,  7],\n",
       "       [ 8,  9, 10, 11],\n",
       "       [12, 13, 14, 15],\n",
       "       [16, 17, 18, 19],\n",
       "       [20, 21, 22, 23],\n",
       "       [24, 25, 26, 27],\n",
       "       [28, 29, 30, 31]])"
      ]
     },
     "execution_count": 91,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.arange(32).reshape((8, 4))\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 4, 23, 29, 10])"
      ]
     },
     "execution_count": 92,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr[[1, 5, 7, 2], [0, 3, 1, 2]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 4,  7,  5,  6],\n",
       "       [20, 23, 21, 22],\n",
       "       [28, 31, 29, 30],\n",
       "       [ 8, 11,  9, 10]])"
      ]
     },
     "execution_count": 93,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr[[1, 5, 7, 2]][:, [0, 3, 1, 2]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 4,  7,  5,  6],\n",
       "       [20, 23, 21, 22],\n",
       "       [28, 31, 29, 30],\n",
       "       [ 8, 11,  9, 10]])"
      ]
     },
     "execution_count": 96,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr[np.ix_([1, 5, 7, 2],[0, 3, 1, 2])]#np.ix_()函数可以将两个一维整数数组转换为一个用于选取方形区域的索引器"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Transposing Arrays and Swapping Axes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  1,  2,  3,  4],\n",
       "       [ 5,  6,  7,  8,  9],\n",
       "       [10, 11, 12, 13, 14]])"
      ]
     },
     "execution_count": 97,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.arange(15).reshape((3, 5))\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  5, 10],\n",
       "       [ 1,  6, 11],\n",
       "       [ 2,  7, 12],\n",
       "       [ 3,  8, 13],\n",
       "       [ 4,  9, 14]])"
      ]
     },
     "execution_count": 98,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.T"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 8.17484876,  3.28984722,  5.24152575],\n",
       "       [ 3.28984722,  6.49253382,  5.3706281 ],\n",
       "       [ 5.24152575,  5.3706281 , 11.27385964]])"
      ]
     },
     "execution_count": 99,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.random.randn(6, 3)#使用random.randn函数生成一些正太分布的随机函数\n",
    "arr\n",
    "np.dot(arr.T, arr)#利用np.dot计算矩阵內积X.T * X"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[ 0,  1,  2,  3],\n",
       "        [ 4,  5,  6,  7]],\n",
       "\n",
       "       [[ 8,  9, 10, 11],\n",
       "        [12, 13, 14, 15]]])"
      ]
     },
     "execution_count": 100,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.arange(16).reshape((2, 2, 4))\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[ 0,  1,  2,  3],\n",
       "        [ 8,  9, 10, 11]],\n",
       "\n",
       "       [[ 4,  5,  6,  7],\n",
       "        [12, 13, 14, 15]]])"
      ]
     },
     "execution_count": 101,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.transpose((1, 0, 2))#transpose需要得到一个由轴编号组成的元组才能对这些轴进行转置"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[ 0,  1,  2,  3],\n",
       "        [ 4,  5,  6,  7]],\n",
       "\n",
       "       [[ 8,  9, 10, 11],\n",
       "        [12, 13, 14, 15]]])"
      ]
     },
     "execution_count": 102,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[ 0,  4],\n",
       "        [ 1,  5],\n",
       "        [ 2,  6],\n",
       "        [ 3,  7]],\n",
       "\n",
       "       [[ 8, 12],\n",
       "        [ 9, 13],\n",
       "        [10, 14],\n",
       "        [11, 15]]])"
      ]
     },
     "execution_count": 103,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.swapaxes(1, 2)#swapaxes方法接受一对轴编号。swapaxes也是返回源数据的视图（不会进行任何复制操作）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Universal Functions: Fast Element-Wise Array Functions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 125,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1.00000000e+00, 2.71828183e+00, 7.38905610e+00, 2.00855369e+01,\n",
       "       5.45981500e+01, 1.48413159e+02, 4.03428793e+02, 1.09663316e+03,\n",
       "       2.98095799e+03, 8.10308393e+03])"
      ]
     },
     "execution_count": 125,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.arange(10)\n",
    "arr\n",
    "np.exp(arr)#计算元素的指数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.        , 1.        , 1.41421356, 1.73205081, 2.        ,\n",
       "       2.23606798, 2.44948974, 2.64575131, 2.82842712, 3.        ])"
      ]
     },
     "execution_count": 106,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.sqrt(arr)#计算元素的平方根"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 132,
   "metadata": {},
   "outputs": [],
   "source": [
    "x = np.random.randn(8)\n",
    "y = np.random.randn(8)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 133,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-1.29686413, -0.31286359,  1.25283388,  2.10836564, -0.88125514,\n",
       "       -0.10467455,  0.85655625, -1.36828618])"
      ]
     },
     "execution_count": 133,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 134,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1.68185656, 0.09788363, 1.56959273, 4.44520565, 0.77661063,\n",
       "       0.01095676, 0.73368861, 1.87220707])"
      ]
     },
     "execution_count": 134,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.square(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 135,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-1.29686413, -0.31286359,  1.25283388,  2.10836564, -0.88125514,\n",
       "       -0.10467455,  0.85655625, -1.36828618])"
      ]
     },
     "execution_count": 135,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 136,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-0.5792384 ,  0.92121659, -1.8623979 ,  1.35923844,  1.06993349,\n",
       "        0.81262757,  1.12506395,  0.41147433])"
      ]
     },
     "execution_count": 136,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 137,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-0.5792384 ,  0.92121659,  1.25283388,  2.10836564,  1.06993349,\n",
       "        0.81262757,  1.12506395,  0.41147433])"
      ]
     },
     "execution_count": 137,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.maximum(x, y)#计算最大值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 138,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 3.78505117, -6.47552934, -5.70296428, 10.03664061,  4.75746147,\n",
       "        0.40842777,  0.332776  ])"
      ]
     },
     "execution_count": 138,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.random.randn(7) * 5\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 139,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0.78505117, -0.47552934, -0.70296428,  0.03664061,  0.75746147,\n",
       "        0.40842777,  0.332776  ])"
      ]
     },
     "execution_count": 139,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "remainder, whole_part = np.modf(arr)#modf是Python内置函数divmod的矢量化版本，用于浮点数数组的小数和整数部分\n",
    "remainder"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 140,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 3., -6., -5., 10.,  4.,  0.,  0.])"
      ]
     },
     "execution_count": 140,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "whole_part"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 124,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 3.79373623,  2.61120729, -8.10306556,  3.76726396, -0.95740199,\n",
       "       -3.5556938 , -2.41490659])"
      ]
     },
     "execution_count": 124,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 141,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "D:\\Programing\\Anaconda\\lib\\site-packages\\ipykernel_launcher.py:1: RuntimeWarning: invalid value encountered in sqrt\n",
      "  \"\"\"Entry point for launching an IPython kernel.\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([       nan,        nan, 1.11930062, 1.45202122,        nan,\n",
       "              nan, 0.92550324,        nan])"
      ]
     },
     "execution_count": 141,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.sqrt(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 143,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-1.29686413, -0.31286359,  1.25283388,  2.10836564, -0.88125514,\n",
       "       -0.10467455,  0.85655625, -1.36828618])"
      ]
     },
     "execution_count": 143,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 144,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-0.5792384 ,  0.92121659, -1.8623979 ,  1.35923844,  1.06993349,\n",
       "        0.81262757,  1.12506395,  0.41147433])"
      ]
     },
     "execution_count": 144,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 145,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "D:\\Programing\\Anaconda\\lib\\site-packages\\ipykernel_launcher.py:1: RuntimeWarning: invalid value encountered in sqrt\n",
      "  \"\"\"Entry point for launching an IPython kernel.\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([       nan,        nan, 1.11930062, 1.45202122,        nan,\n",
       "              nan, 0.92550324,        nan])"
      ]
     },
     "execution_count": 145,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.sqrt(x,y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 146,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-1.29686413, -0.31286359,  1.25283388,  2.10836564, -0.88125514,\n",
       "       -0.10467455,  0.85655625, -1.36828618])"
      ]
     },
     "execution_count": 146,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 147,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([       nan,        nan, 1.11930062, 1.45202122,        nan,\n",
       "              nan, 0.92550324,        nan])"
      ]
     },
     "execution_count": 147,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Array-Oriented Programming with Arrays"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 148,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-5.  , -5.  , -5.  , ..., -5.  , -5.  , -5.  ],\n",
       "       [-4.99, -4.99, -4.99, ..., -4.99, -4.99, -4.99],\n",
       "       [-4.98, -4.98, -4.98, ..., -4.98, -4.98, -4.98],\n",
       "       ...,\n",
       "       [ 4.97,  4.97,  4.97, ...,  4.97,  4.97,  4.97],\n",
       "       [ 4.98,  4.98,  4.98, ...,  4.98,  4.98,  4.98],\n",
       "       [ 4.99,  4.99,  4.99, ...,  4.99,  4.99,  4.99]])"
      ]
     },
     "execution_count": 148,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "points = np.arange(-5, 5, 0.01) # 1000 equally spaced points\n",
    "xs, ys = np.meshgrid(points, points)\n",
    "ys"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 149,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-5.  , -4.99, -4.98, ...,  4.97,  4.98,  4.99],\n",
       "       [-5.  , -4.99, -4.98, ...,  4.97,  4.98,  4.99],\n",
       "       [-5.  , -4.99, -4.98, ...,  4.97,  4.98,  4.99],\n",
       "       ...,\n",
       "       [-5.  , -4.99, -4.98, ...,  4.97,  4.98,  4.99],\n",
       "       [-5.  , -4.99, -4.98, ...,  4.97,  4.98,  4.99],\n",
       "       [-5.  , -4.99, -4.98, ...,  4.97,  4.98,  4.99]])"
      ]
     },
     "execution_count": 149,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "xs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 150,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[7.07106781, 7.06400028, 7.05693985, ..., 7.04988652, 7.05693985,\n",
       "        7.06400028],\n",
       "       [7.06400028, 7.05692568, 7.04985815, ..., 7.04279774, 7.04985815,\n",
       "        7.05692568],\n",
       "       [7.05693985, 7.04985815, 7.04278354, ..., 7.03571603, 7.04278354,\n",
       "        7.04985815],\n",
       "       ...,\n",
       "       [7.04988652, 7.04279774, 7.03571603, ..., 7.0286414 , 7.03571603,\n",
       "        7.04279774],\n",
       "       [7.05693985, 7.04985815, 7.04278354, ..., 7.03571603, 7.04278354,\n",
       "        7.04985815],\n",
       "       [7.06400028, 7.05692568, 7.04985815, ..., 7.04279774, 7.04985815,\n",
       "        7.05692568]])"
      ]
     },
     "execution_count": 150,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.sqrt(xs ** 2 + ys ** 2)\n",
    "z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 155,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.colorbar.Colorbar at 0x1f1a9d11b38>"
      ]
     },
     "execution_count": 155,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAATAAAAEQCAYAAAA3VyjFAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAAIABJREFUeJztvXv0bVdV5/md94b3IyFEMCTRQEtjA7aAKQiFQymgrBApUmWDgJYGxJHuLlGR6oZgPaBtezRa1Qo0XWiah0DzjlBQFIoUkLKthkgCFK9AEUIkl0TCLSAgoJBk9R97rzDvvN8511x773N+58CeY/zGXnuuuR577b0+Z6651zk/KaVglVVWWWUf5dBBd2CVVVZZZaqsAFtllVX2VlaArbLKKnsrK8BWWWWVvZUVYKusssreygqwVVZZZW9lBdgqq6yyt3LCQXdglfkiIg8F8P8ddD+mSClFDroPq+yvrAD7zpDHriBY5btR1iXknouI3ArANw+6H6uschCyAmz/5ccB/L8H3YlVVjkIWQG2//JjAP5DxlBEHioi7xWR/yAirx29t43Jtttb5btPVoAFIiJXi8ijttDOfUTkgyLyVRH5lc7iJ5RSvpW0/QsAjyil/DiAqwCc19lWr3S1N3Mcti4i8jEReXiQ/wci8psT6t3YOGzrmd6WbCyILyJXA/jFUsq/31QbuyILXOszAVxSSnlgZ7s/BOBjWftSyrXq9EYAN/e01ysT2ps0DgclpZT7bajqvRqHg5TVA9sN+X50gEjJowG8vbeQiNxzLPu2ht1zReS5E/o1qT1MHweIyNbeqG+hrcnj8N0mWwHY6Lb+zyLyYRH5moi8VETuLiJ/NLrJ/15E7qLsLxSRT495HxeRf6jyHqTc6zeKyOu1my4i9xCRPxSRL4jIZyIXfOzXs8c2viQiLxeR2zq2/42IXCIiXx6XDo8d9a8C8H0A/q2I/JWIPLOz/LsB/B0ALxrL/9cdQ3uXUsqXTDu/LSJvVuf/UkTeVeNPInJnAK8A8HOllNlvL0XkjiJyk4icqnT3F5HrRORO2fbYOHhjpspcLSLPEpEPA/gaA0v0LBFb99libdnlmIg8UEQ+MJZ/PQD6LI22k56H8XouNroXiMgLe69ZRIqI/IA6P2bJG82lcSw+N7bxSRF5pHetG5VSykb+AFwN4FEq/T4AdwdwGoDrAXwAwAMB3AbAuwE8R5V9PIB7YADsEwB8DcCpAG6NIa7yqwBuBeCnMGwh+M2x3CEAlwP4F6PtvTDEXv5e0MePAjgDwMkA/mOtS1/D2NaVAH59rPcRAL4K4D72Wp12WuUvwbAE9co/GMBHANxa6e4O4OnE9q4AvgzgAQD+h7HciWPeCQD+HYa4VOYePhfAcxN2HwPwk+r8bQB+eUJ7t4xDa8zUuH9ovH+3c+qkzxKxaz1bx7WFY5/xWv7XxvKPA/At/Twt8Txg8M6+DuDO4/lhANcBODtzzabPBcAPqHJ/gMRcAnAfANcAuMdoeyaA/2pTLIn+trmE/D9LKZ8vpXwOw2v/S0spHyyl/A2AN2OAGQCglPLGUsq1pZSbSymvB/ApDJP4bAyT4oWllG+VUt4E4M9VG38LwPeUUn6jlPLNUspVAP5vAE8M+vWiUso1pZQvAvjfADyJ2JwN4I4AnjfW+24Mk5TZMplb/q8BfAnDJ3OVnwRZkpVS/guA5wN4JYBnAzi3lHLDmP0kAA8B8C/GT/8nJNtvyfsBPAgAROTHANwXwO/PbC87Zi8c7983WCXBs8Tai56tVltnYwDT88fyF2MYlznXxq7nLzB8+P+DUfUIAF8vpbxvwjVHEs2lmzA4HvcVkVuVUq4upXy6s/5FZJs78T+v0t8g53esJyLy8wCegYHsGPNOAXA7AJ8rI/ZHuUalvx/APUTky0p3GPE+KV3+LzB8clm5B4BrSik3G9vTgnoXK19K+bCIvBLDW7x3jOp7l1Je5hT5IIDnAPjZUsot11dKeRWAV0VticjbAPzoeHrbUff08fzPSimPIcXej8FTBYDfBvDPy7BcbLYXSHbMrkEgwbPE2ouerVZbrPxfBLZznqfXYIDdKwH8zHh+i3RccyTuXCqlXDk+E88FcD8ReQeAZ5RjX9psRXYuiC8i34+B9E8DcNdSykkYlnmCwVU+TUT012bOUOlrAHymlHKS+rtTKeXcoEld/vsAsJtwLYAzROSQsf3cmG79Y4FW+Yy8FcBjZJDbYlhGHCcyvJl8MYa40y901A8AKKU8po4dgOdh8BLqWDJ4AaMHJiL/HYYPmdf2tkskO2bu2DeeJSutZytsyyn/fY7t3OfhjQAeLiKnA/iHUADrvOavA7i9Ov9elQ7nUinlNaWUH8UAugLgt5J9X1R2DmAA7oBhQL4AACLyFAD3H/Pei8F9fdoYRD0Px7rGfw7gK2OA8XYicngMKP+toL1fEpHTReRkDDGJ1xObSzHEEZ4pIreSYe/P3wfwujH/8xhiBJ60yjellHI9hofqRzB4O++2NiJyGoB/iyH29Y8B/JAE+5QWlP+E4eH/PwBcaDyLqTJ7zBA/S1Zaz1ZL3othq8ivjOV/Kig/69pKKV/AECd7OQbIXKGye675QwB+Zpwn52D4VkcVdy7JsE/tESJyGwzhjW9gGLuty84BrJTycQwT4b0YwPBDGILrGJclPwXgqRgC1f8IQ+zgb8b8mzA8CA8A8BkARwG8BMCJQZOvAfAnGAKUVwE4buPh2O5jMWwFOArgXwP4+VLKJ0aT/x3APxvfKP1PE8pn5S1jPWdjGJ9bRIa3fW8H8DullLeWUr4O4F9iiOttVMY45kcAXF1K+aOF6pw9ZtGz5LTnPlvJ/v4UgCdjiFc+AcCbAtu5z8NrMHyQHbN87LlmDC8s/j6G6/1ZAP9G1RPNpdtg8M6PAvhLAHfD8OG/dZFjl+z7JyJyKYDfK6W8fELZq7FHm21F5D4ALgbw1lLKPz3o/lQRkVtjeKv20zqYvO8y59laZTuycx5YS0Tkx0Xke0c3/XwA/y2APz7ofm1DSimfxPCm6/KD7ouR5wD4j/sOr+/mZ2tfZR9/D+w+AN6A4c3KpwE8rpRy3cF2aavyrzEseQ9cRORBAN4D4MMYgsn7Lt/tz9beyd4vIVdZZZXvXtn6ElJEzhm/enCliFy47fZXWWWV7xzZqgcmIocB/GcAfxfAEQz7h540vjlZZZVVVumSbXtgDwZwZSnlqvFV8uuw+d+kWmWVVfZExj1mH1J/X1HfBDlOth3EPw3Hfh3jCIbvyt0iInIBgAsA4A53uMOP/OAP/iAAwHqKzHPUula+Z5Mtu7S+lZfJz9osUWYbcuym9mXLRHZL5nn2c2xbZTN16/PLL7/8aCnle2jjSTnnnHPK0aNHm3aXX375O0op53j545v2B4x9PIzh2wlv9uy3DTB2h46ZPaWUiwBcBABnnXVWufTSS+m30G+++WbcfPPNtQzNZ3qd75XN/NXyXh1MH+lsfdo2o2PHls6mdR+ykoFfL4gOHfr2wsCbeGzC9hy9tO6DtWHnns7WWeub8pctX8dN29pzVs/hw4e972ym5ejRo7jsssuadiLS853MRwL4dBm+wE5l2wA7gmO/X3Y6+HcPbxEPTAxALWhZ+OhjnYhM1wM/po90DIQsHekyR52OQNXjfWbFK+95Cl7/Dh06dEtdGhCllEnHKF37UKGg8+y5vg6mt/XV6+iBmC3P5Oabb77FVsPq5ptvvqWMzlta5j4nRJ6Ixvdqtw2w9wO4twy/0Pk5DB38Gc/Yg5MGSA+0lvK6IjDNAZcHqghOU4HF7LxzTzdHKjAinfWy7HV4QPOOvRADcAw4GJwYiKqwvFofg3dmzHR55n1pqbCyEKt5S0Ms6cGfIiLaVbuoDKuuY0SGb3c8FsNPQrmyVYCVUm4Ukadh+EmYwwBeVkoJfzq3x/vxoDOlXE+7rXp1fsvjasEpgpk+2ofJA1YEMk+XydPCJisDlYVRBYBNVxsPaAxUug6vXi/NPDLWJ62zMLP9ngoPr3zrXrByS34o6WezIUdLKWcl7B4N4AOllM9HRlvfiV9KeTs6fsfdg1Dkedm8DLy8+ixwsiC0NhmPywNVBKseYG0CYp6N9UQ8YV4Xg5tOaxsGGYDDbIoHZoGkQdZaTurrj5aE2WVkvaZDhw5RjyrjjbHl5FKyJBAx/N5Z82eZdv6rRD0QigAU5bXglYWUl99aekbnNe3pvOC/PrZ07Nx7GLMPqWfHPBatZ+cZD0rrGMxa5b20tyRkIGNj4EFN9zPrjVXg1Hq9sq0PjE0sH1vt9oiI3B7DXtH/vmW70wCrk38JzysbK5sLTF0mEzOL8lkekINWBmZROtJFek8soGye1lsPy0trnbdsZDCb44FZXYWBtYvAZaUXKFFsS+dnPbGlZCmAleGnoO6asd1pgAFIgYTBaU7Ma5NbLDI6fV7TbIm4SXj1wCwjtixbYnqeUM2z+gheLZhZr8ymo3O7rGXxMW8M9FJQ11XrOHz4MEopabjskie2FMB6ZOcBBsQelAevXuDMAZcu49WR0bHznv1hmaOn82zYvZgjnifWin1ZyFlIVV0GZhY6Wq/T7Lz2nXlbmbgW4MeeRAQ33XTTLTEuFgOzEnlUEaDqNUzZ++fVt1RdPbLzAMuAJwuvVl6rvVZfdPmoLpZny+r6WL2Rjh1bOpvWfdi06O0QQP8SUucxvQcx4Nhr9ALzVawuApnnEWnPTwfl9bV75TOBemDw4mwZD27ZZW5G5n64TZG9BthSENrkFosMsJYG1xR4tWC19MOpJw5rO7PE0zrvyGxYXSyeZduIlpf22jSEdHkbv7Ltss2nTLz7YT3ZyH7pe7oCzIgGBINGdN6yt/DpXXZ64LLnc8E1B2TsqNti483Sns1UYZPMwsDrY53U3lLS87YinU4zj8zzuLTYvJ7YWL1eBjjgWI/K2s/xxNYY2BZkKkgyYFsaXlNA1rs/TOszunp9bFxZOnMe1aXF81CqfeTR2HNvydeCl66L6VhbtT3mRdnr8IDm1dMrnkdVxQNZ1hNbCjr6+dum7B3Asp5XBKWbbrqJ1p35q2WnlNdlsm8qbX49Zzb66G1s9cAVAc3TtSQq0/LCMrEve412i4QGTKRjHlZNe28tPWiVUtylo+6j/YsAZ8t6XlcmiG/HfMk45xrEN9ICUS+87J6yXvD1xMo8u54tFvq8lQb6N7Vm05Fuinjw0jrmfXkgq8dov1e1iSAWQY0tB21ZFuey15gJ0HseVS0b1dGCWLT0nCtLPR89stMAA2LQRPm9ZTJg623PQiYbM9M6z97WacdLn0dHm86cZ/OA+HuQdsmodRo8NR3pLHjYNgmvXt2H1jLWekO9kl1SMhtd1ht3W85rb2nY2OduW7JXAMvs1/I8qGjZmHkBUMvquJk+9oKzdR6BTLfLbKJjS2fTkS4jXrmWF5ZZQnoQ03aRVxYtHa0HZfUWCja/9WffPDJhXpmGqOdJ6XH19oltAjYrwIhkYND68+CVCd5XGyAX7K92tb2ov0xvdfo88rY84OljS2fT7NzTZSTyuKqu5Sl50GIQs21H8Szbju2Ttxys9U3xxixcW6LHLPLEmM5CbAXYlkRPXguGDJAYvDIgmhPo98AV1cfy9LXq8dC2LJ05errMeZVs0DaaNHaJpm2iOFgWYsyzyoKs5YV53liPWI/Ki4EBx8avIk+Mxblq31txtDmyAsxICwgRkFjAPvtCIBMrY8d6A+cG+6suWib2wqsFLp2e+jap1mG9kV7Q1Tp0fRpOug129GJjFlQsTtaClr1eBsXW8tEuHRkEI8DUvBaQ7D2tbbfiaFPEPq/bkp0GGMAn61QPaG65nlhZC1JR/hRwZSDGjsDyPzHt5XvLLBavAnI/g5PJ0zqbZh6ZtmF99vKy3liFSb1v3u77aJw1yD0g2XM9JrUPS8qSQMzKXgAss+TTf9llo9X1eGxzgclsvS0W+ryVjnRAe1Nr5rylt6LBwfL0ZNTC+qq9Fg9iGQ9Mpz0vqvaZeVHRtWaXZyzAbtPekpItJ9n4eV6dXa4vISvAiEzxpHrttw0v1lddB6tL61ppq4ugpR+6qSBriS1nl2hVZ0FW4aF1NvBtQaXLMZ3XPxbTisqwOnSZ2k/2NSAmGlaZ/Vy6XWDazvul42ArwIzoCWiBEcGkpYs8r+wykcXYpoC1B1w9IGNvLNkxSrNzT5cRzxNj8S6WtkcPZjWfxb30eZTXWlayP+sFiXz753FsDMwTb9sDGzerY9CM7qcdw7myAoxIaxJ7MMj+bSJWloVZT8xM66K098ZSH1s6m2bnU8ROHq1vxapq2h5rXRFwdNrzyOw5q3dKzMgL0LdAlo2JRR8GLN/mLRUH03Nim7IXAIs8qJq2bwOZbQShHq9uLrx6tlhEdrrverx6jp4ucz5V2HLHei42HcW89ET0vLKWB8ZgxpaVdjwqiGyZzG74CGTs7SKz93Te1pUIbnNl6foyshcAawEpCy9vq0Rm2cnaYm1mwcWuLYKZ1ek+6DxWv9XpMp4ue94rHryqrmcJaY8ezCxgIqhFMGNbJWo7LICegaC1ZXDKbLHQY6rLRF7cCrAtSGuyR96Qpz+IZeOULRaefXabRc8xSrNz7z5ViQLmNl9Dx0tbW3tkeVUYyFjbrB1vWTk1+N0qy8Y5s5y0966Wqb+x79ktKSvAiNTJ3zPJozJzPK8p4JoCPmYLtH+tlcGpB1wtaC0V42B7lqJlI9Oxo6dj/W/9WKEHNb2cs/W0vtto+5H9oULmiUX3qtrVlwheUH9J4OhnbZuy0wCbCqmlQDK1XLW3+9FqOlOfzmce1xyI2XyblwVV9oFlyysmUzauRja6nxaQFgaRx2iXgRqmLEaV8dDYUtq2y8roLR6evbcMt3ZLA2ep+kTkJAAvAXB/AAXAL5RS3stsdxpgQOwp1fzMn4VJJtif+T5kxtPL/DHbKGamz1vp6OjBJJogLdsqGixenj5nfclsXNWQYUBreWTejxV6nhjrtxegZ7Et277niXkvDdgbVwvSTFB/aYAt+BbyBQD+uJTyOBG5NYDbe4Z7AbC5cLATO+O5zf0Fi1p2ztYOVs7q9DlLWx17yLyHugdi3r1j4gXybZpBTQMtAzENEQuoKgwI+hr08pABzn6/sCdQz5Z53vjppaG3bcTa2vNoGTpXlqhPRO4M4McAPHms85sAvunZ7wXA6nEOEHrsGSh64ZNt17Zjr4/1w+o8ez1+FgQ239Oxc08XiV3SMV20FKxHFpBnZVl/WXvectDmszeNVfTS0V4XEwbv7BjrsbN90vYsfmiD+ksCTD9zDTlFRC5T5xeVUi5S5/cC8AUALxeRHwZwOYBfLaV8jVW2FwCbA5asx5QpE9W15M/vRPXYPH1u05n9YS2dd97SV/GWkXbSenEbCzALMiDeJmFBZM+tLvLGMlI9quoptX4WR+uAvv8kFMW32JIysl9CkvUdLaWcFeSfAOBBAH65lHKpiLwAwIUA/rlnvLMSTfIeKEwp0wugKWVabXp1Wr0+B3LgygDNpqvMiXXY5QvznHRa98NbMnrbJFjaq1dLNhDvSRRst23bchmdB6rMB8KuLyEBHAFwpJRy6Xh+MQaAUdlpgAHTl47eUi7yono8r6pr9avVXi2buTZrw8bH1qdtvDxbLgOo3oeVeU5WbGzIHiOI2bq1x+F5YJEnZsHIYl8sFqb7r5eUzKblYbHz2k/bjoVlBLYMXKfIEvWVUv5SRK4RkfuUUj4J4JEAPu7Z7w3Aaro3AB/By+bp9lrgYmV6Ym29Wym8POZlsnR0bAX22bmnY+J5FvacBexrOQa0KGAfvWG05wxmtl89P49TocTKem8sI5voXtTrYDE670PKs58j9lmcKb8M4NUyvIG8CsBTPMO9AJgGQ9VlJ76XZhDIwmdqmTllrX0WXFlo2Yecpdl5RnQZGxPzlo0WaNEbQk/vxbS8cl7f2VdyMuX0dURAYoCPlnrs/kQxxYz9ErJUfaWUDwGI4mS3yM4DbM7S0cKPeWDVvifYn/XWvLZ6YdUDrghe0TIzm2bnWYkmWT23em/paZeI1ZYF79ly0F5PtDS0bxkzP4+jl4cWYhmvTJeJAKjTXhsewObE+ZgsDcSM7DzAAD+W04JXq1xvDGoKvLKxsgzIWv1l19raPuEdbRpY9qtEun7rhWko6b6weFfGM9NldfwnWjp6kvGobF9suVZgXvfZbn2wtvYDwLbhBfPZGM+VvQKYiJwB4JUAvhfAzRj2c7xARE4G8HoAZwK4GsBPl1K+JMNovQDAuQC+DuDJpZQPRG30gMWzjTwwbZ/ZSjElTjYVXlPBVc8jTy062rLePZkqLNZVpRXz0pPOela1vOeB1b57y8qar+HqbUxlHlUmUG8D+5ngvUj++4z6+uxS3UsvGLfaL4ABuBHAPymlfEBE7gTgchF5J4YdtO8qpTxPRC7E8Ar0WQAeDeDe499DALx4PIbSAlTVeV6QLqPTPQF3r/3sspP1ewq8WtDS9uy67bH1EHsPv2fDxAss9wTxrTfBAvH1OtgvTmhb2571xjSM9NLRwixagrEx0dfN3gJGy2ub10qz+Berb4eD+GmZDLBSynUArhvTXxWRKwCcBuA8AA8fzV4B4BIMADsPwCvLMIrvE5GTROTUsZ6oncUgMXU5t8Q/CekFpu1j1F+g/5cqMkF8OxFbsLIT0CvTmqz1aL0rCzGb1tflLROtLlqKatEws+VbbxV1ee2JaYC04mKtmJZOM0hm7u9cWbq+jCwSAxORMwE8EMClAO5eoVRKuU5E7jaanQbgGlXsyKg7BmAicgGACwDg1FNPTU32sa1FYefV74HIg9cUTy/Tx5ofLS/1ee1LleiB9iYIO/fEs8t4GgxoHsw8oLVAZkXba2+rHiNpAYuNS10a1vZYPXYMmefm3cfMUnIFGAARuSOAPwTw9FLKVwK3lGUcd8Vl+F7URQBwv/vdr3iAqjoNCGbnTcoemEwF0Kbgpe2sLTuP3j5m4bX08oAF8jW8vOfIg1Oty5aL4l0WajZGZZeQkWSXkxbeVuelNcj1Ndrxm6JbSvYOYCJyKwzwenUp5U2j+vN1aSgipwK4ftQfAXCGKn46gGtbbSw12Xtg1LPUzAT/M/nZawFy/wykBa0IXJmYWEafgZCWVhC/Hj2vzIuNWehFnli0LPQC9dom2jXPbCKvi6W9eJhnm1lKLiH6mdqmzHkLKQBeCuCKUsrvqKy3AjgfwPPG41uU/mki8joMwfsbSiL+VY9skjIbT9ezdOy174XQHBB74+L1PRqbemQwaT3omYfV2liPgwXVtfQG5GsZ66G0YlZWMnbe9We2WERQy0DLbpXwbPU4eXZLB/K3LXM8sIcB+DkAHxGRD426X8cArjeIyFMBfBbA48e8t2PYQnElhm0U7tcDtHjg6oVFj633VaQMXLIxMg9eup569JaLWXBF46fr1ccoHemYsKWS95YtCuJXfRTIz3hazIb9VbvsTz/rPLvForUTP4pvWSiylwDR/WOAZPZzZd/eQv4ZeFwLGL6Aae0LgF+a0M5sIPXGomrdreWhXWpm3kz29qtnuejBytrpsY2OUVqL9+B6X4VhgXyrt0tGtlz0IOaBjC0rM95Y3YdVyvEBfa+O7NKwnkdQYukpS0n7W2C2jrmyZF1Z2fmd+GxysYlf86yuZzuCrbtlGwEm+sv+dlir7sgz07opQXz9ME79ZG2Vs1+0rkcrWm/hZPO1tCDVCzHvFxyYztbdAlgt4wHIpnX99gWItfPylobXCjAirUnNbFpgWwJGemnnQZXpWvBiS0h2PVMC+QxSWWBlJy6TCC5W9FLRHqPlYu2P52lVu2ipWPMZ0LSdtfGWid7SMPLOouWe1VmvzbPT/d/UL7Juor6M7DzAAB7LsXpvkkcg07pMgHwq7HqAOsfryoCLjSEw/dcpsvevihfIr0cW99L16PIeyKx9JoCv8734lgckdp0WHPalgzemEWgyQXutYwF9ZrOUrAAzYid+y/vS55sM8rfsez0vG0ubCreeMdK2WpcB19QHlcW+PJAtFfey7WsAZb/jyALoNZ3xpHQczebZchY0Oj8CJNsqweyjbRVzZQUYEW/ytWDCdFngtILrvS8FMl9Fit5GMnCx+rTOG5Mp8TCbtvVkJPrunxev8ZaBGly1b8zTsnr2QsDmsZ+vsSCLlobazkKs58OhdynJ7Nj46n4uGcTXz+A2ZS8ABrS3TXi2rIzW2bZa8JuydLT2LXj1tNdaUla9B64MvJZ4MKN4lwcve+wJ4HvLyireklIvI6NNqWxpWPUenGzQ3dpYqPcsJVndbBx1+aXgxa51W7IXAIugwvRW55VlMIn+psAr483VOnvA1srXdda0PXrQagXxpz6odrK3gvgexHTZTADfLtdavyhRwcQ8MbuctD91Ey0PvXgd+9Cw0InsdN362tk91vdgBdiWpDUJvUltbfS5rTcDQ6/NJeDVC8spnpk3HnosdBl9tGlmy4RNGLv00zq2VNR2tkzkaVVbGxvTS70ouO8B0NpYnQcYex1WzwAWeVY6HR11e/p+sw26c2QFGBHvBngT0uqWAlJv3MsDDAvYR55Xj1emy7Cx8eyi8Y3S3r2KPuXZUkaXsSAD4l+fiAL4uh+eR2XjZlqYJ8YC+62gvLVpxbe098SWqux519eYgeSS8S923duSnQdYZtlW86OJa/UaDKx+rWvFmbLwyuTr4D3rc7be6Jq2Hchnk9vzrOzRC+BrsbZTN65mPTE7+W2+B2gLmt6tEnqsPDi1YmB67KKx6BX7XG1Ldhpg3kRsTbKo3BQgZe162rYQZedLQVG3F40TG9PWQ2mhZkUDiImFQjbupfOYp1XtrKc2BWI2sM88Ll2vHjtvJ/6c+Baz9+AYfTDZD4K50noWNiE7DbAqbPDZBM4Cxaujt96WvU23PK8pffDq1DrPM2NpIL+p1bMB+Be4tb6mvaUig5gGhbWfAirA/6K2zfMgpa8xAxqdbi0lLWx0Ox6QrG0LYEt6TUsBTESuBvBVADcBuLGU4v6LtZ0HWOZGtOz1JM0un/TEt/V4EIxeCnj1RBCaCq9W/1kfpwTxowdW59kJ3QrIA+0fK2zDoVOvAAAgAElEQVQF8LVNlO9dg+chRZCy5aLloK4rWkpqew1PtvRm9eo+2jrtmM6VpQA2yt8ppRxtGe08wIC2t9SKZ7XA49lkbCOYRN6YLcdAlYGXFzNrBfL1pNDjrG2Ynt2bSBgkLIjskcHMTthMAN/mZ70tnde7KVXbtsbQAorZaSjVuhkkvWPGbgmxz8y2ZOcB5kFFH62tZ9fyWHSe500xnQe7qvPqioLuWXh5ea3rjOJhmbGesvSINp9qnU7bZducAH69TvYVIjb5dJ3WxotveZ4ZA5K+F+xXJTzYePeLQSm6n5EHOkWSdZ0iIpep84vK8DPyx1QF4E9EpAD4fZJ/i+wFwKIjm8StchGUMnkMGp6ewcbGw7LB/OwvWWTAlYGxto/uTUa8eAsL4tdz+8ZMl4kC+K24V7W1WyEA0E2pbKnaiod5Hhv7QLDxwhZ0dFof2b2LwLgkvGp7CTlagpjWKA8rpVwrwz8EeqeIfKKU8qfMcOcBBrSXhNUmsm1tMcgApBcaXl5vzKv1AkDXWctb2+j69Xmtw46/PrK8SOwnfSbuVY82gG8hZe3YktIDj4WdiL+z3kJM65nH0wKctqv3h21YZUcvbsbq1mPkHZeSpYBYSrl2PF4vIm8G8GAA+wmwaFDYpFziqNv2oMk+8SK7jD7y5LwyLa/MjlMWXNHY9D6orQlV8yzMdHk70XoC+La/rTwLW92+BU8UtG+VYQF9PR4RcFp1WjBGNkuIfo7miIjcAcChMvyv2TsA+AkAv+HZ7zTAosneyssCoMfW6qe8IeyFVPRLFlmvLLqOqUH83ofVm+hsyci8qDrhmF0LYrr+6pHZNrR4wXsv7pVdSnofCgwoLeDYNiPY1fyWzVxZCIZ3B/DmsV8nAHhNKeWPPeOdBhjgezqZclOOUZsMDiyP6QHfE+qBZhbKS8TDvPGZEsAH2r8gYSdWBBkt0ZtEBjkNDrsEtGWYl8R+Goh5TzqvLvm8JWItq20j4DHxAOXVuaQHpvs3s46rAPxw1n4vAMaO2TeKmbr0pI/qyYDFqycq4+m94D679oxXVvXeW1GWZrCa+qC2gvhs8nlxLeaN1d+t97wt762hjXvpia/7qPXeUs/W7+VZndVnjrof2TL66H2QTJUlYZiVnQcY0AZPZJNdPnrtMbsoVuTled5O75JyyksDm89s7HhmA/mth9YuY/S5hYQ3oTTMMkvGyNvKxL10Gd2+Bx+vfgub6Bc2bD0e0FtA0n2y4+m1vYTY52tbsvMA88AU5UUTMwM6W4dXPrKZAyP7RjGy30Y8zI77nCUkm9y2Thb3qqKhp//VWT1aiNntDDom5v2ihL1WBj0vBmXho/NqmsEvCyRbnz6P6mDL2KXgpfuxbdl5gAF8gmdAMuUtZQtYUzwg7xoivYVXNpifgR6rx461vvallpHeEtKDWbRVQi8ZKzQ0PCzE2HJSX0M2vlV1ul49HhYOGmQMevr6poIpesuoJWMzR1aAEYkGJZPXAp2d5HOOrJ0eqEV99uznLCkB/0cds0vIljfmbYfwYFWFxaCsREvKzHKSwaIV32JpBmAGNtsWA5K+L9ZjiuBT6/DqjWJlS8kKMEdasPEmp8235VrHHhh5LwCYfeR9tdL6vNfzauXX67D9tnp2f5hoCFnRyzpdP/uFCetl1D+2TKyivTIveG/vkdXr/Ix3FtUxBUzRs2nja/UlRFSf1/ZSsgKMCBsUzxvQumjZw8p7EMyCjrWRhZrur217iWC+hSHrQxZc7Fo90RO6SuR5RV4X03tLRi3e0rCWz8S9mGfFvBh2vVkwMehY4Nixjbw4lucBcwmxz9C2ZKcBZiHhgSKCTivPxtOiI6vTAsKzr2nvrSOrOxPM97yzDNg8cEXB/NqfqeJ5XjWPAU5DI+tt6f57YMzGvTSYGKyYZ1PrzYDJez6zgGIS2UTl5shSMOyRnQYYkPfAMjpmE9kyMET1RPYeQHqhFumnwiuCGRB7Yd54AsdvuLRLSrsstJCxOmvX+gkcfc7q10DJelYsEB/ZMq8rWjoy2NXrjmDWakvfS7updSlZAeaIHnwPNBk7bW8ncKtO2xc7uVm9Xt2svM3zYn0epFpLSt1e5HV54GLjkfXE2A58BjMGMm+J6C1/mK2GCruWDKzYMrDlVWXAxOrS7ehrWMqj6rXvqXfbshcAA/q9LVY2so9sIjhova0nA5ge26nxsMg2AlcEW3ZfPGHl2NJQ6y2IGJiYJ9YK3mfjXhY0Hti0rT3XY9SCWlbneWD6elp29XxJkOm2tik7DzBvYCJ4aL0HFtaGBxdWN+BPdNZHduyBmtfX3mB+9rweveUjuydeAN5OlExMKnNedawvDDQ6vsb0uq8WDB4wPC9M32PPi2vVx8Ywysvq7FvLpWQFWCB2ctm0tdPCJh2rL7Kv5xGU6oTPQsbqbL9sHRFkrY3nebEXA5lAvu1fJJFNK+6ly7PYVdYT05OVBeNtbKnWwzwrnW6BqQdCDHjaRrcVBf2rzrPz+sX6OEfmvNyZKjsPMAYsDyQMCi1dy96CgPVJ57G+srZ0va3+90KNwcura44XZtOetOJewPHeW8v7anliGlbsvlkQ6DYs8FoeWwTGpeJdGfueshbIc4XNgW3I7P9qKSKHReSDIvK28fyeInKpiHxKRF4vIrce9bcZz68c88/MttGaMHMGrre+yBOJJr8HOltnFpSteBhrv3dJedNNN1GbmlfzW3833XQThbbOs2PAPEV7HoHaK6PH1BtvNv5M3+PFsw8qdm+jPngfdl7bXv6mhH2YsmtbUpb4t7y/CuAKdf5bAH63lHJvAF8C8NRR/1QAXyql/ACA3x3tJkl0c1m+veEMNOwB8uDTKsfa1MdoSWn1maUjA1CFR23Pg1WFiAYHq0sDLYq7eX31YOb1of554GNwsucZfeYeRHDM3G/7XLJnwbOrEoVQ7HWy/rBncGmg7B3AROR0AD8J4CXjuQB4BICLR5NXAPgHY/q88Rxj/iMlsQBnwNFpdvNsvtXNkUwdzMZ7uNmDx+rIAFinvTGzkGJgY56N54lVsLE/Zluv1cKp6j3oLAExD2xsfL37wCSCQwssvTrbJutHtp/Z68vKQQBsbgzs+QCeCeBO4/ldAXy5lHLjeH4EwGlj+jQA1wBAKeVGEblhtD/mn1eKyAUALgCAu93tbrfosw+UBzmmyzzg3kNv9Z4u6nurLW8ierZar9MeCKbEw+r1R+MO+N+DXCruxbY26Fib7XNr+4ONEbG4lRcf875fGNWv03oMW3b13nhBelsPy9+E6OdlmzLZAxORxwC4vpRyuVYT05LI+7ailItKKWeVUs468cQTadvRp5SXbn0CZD8dej/52ORnQGS2rI4M1Njyj+m9MuzcWz4yj83T12tlcS+7hKw2dswir8zW2Xo+onvSuo9RfdG9nFJHS1rPZCa9hNhngP0tLXM8sIcBeKyInAvgtgDujMEjO0lETiiDF3Y6gGtH+yMAzgBwREROAHAigC+2Gpl6I1qD1XqIomWaPmewydh6E4JBzYOK7msLUq14WAtktt3eT9to+4TWaQ+r/tSzzvPStU/2y8+6z3brgrf9QadrHdYL6n3T572hrGMcbX/Q5fW2i95tEV6ZpWQTgGrJZA+slPLsUsrppZQzATwRwLtLKT8L4D0AHjeanQ/gLWP6reM5xvx3l8YVZz/RMmXsp62X32qTTVwWb2K61rVY0LF+2bxM0LblebXgVdNREF8H3j3Py3paVa/fdlrPyeZZO5u2fdLnzCa6L60PETamkS66/9nnuvV8R8/EpsWONftbWpZ4C2nlWQCeISJXYohxvXTUvxTAXUf9MwBcOLchDyzeg5EdwAg6Ou0BJoINmyRsstvyrC8RzKLlVS+8IvBllpBekN1CyLPPjL+97mi8PDB5985KL5RaOq/uOfDJzIGlY1YHAbBFNrKWUi4BcMmYvgrDf9K1Nn8N4PG9dTMwRRPT2gZ9DuvSdtn6e3WZPDbBGFR0+WgZ6cEOiLdbRJPbG2sbaLfLKcAP4Pek2bJSB+On/rKp1dV+Vl1PYN4TVj6jy7bfamspWRpQInIYwGUAPldKeYxntwkPbHHpAVOrfE+9WQi26szoWvD0yjOvgtXfio0xWEWeCvOWGGCj89pvdj4lnRlfVs6Ooaer0goZtOpjfcx6Q5mVhpbsM7qE2DAC++sQu7+Uyl4ADOhb/lnvpaajuJQWz+ub++BGOlafp2OTk/XRWxaxcjbNYlIRxDJ/zJb108a6WNzLjofuszfOmQ8UNl7eGNo6PInajdqJ2vTaz6Q3Jd4Hmf3waIndXxrJzn8Xkgm7yVpv05m6etNTHqrooWUPb6SzXkjUN7t07ElHD2JrLNhSzVu26KWhfWOn0/qa9ZLR/rpCzbft12O19fZItXSt+qK6p7QTpb3xtL+Tnyk3R5Jz7hQRuUydX1RKucjY2P2lruwlwKxMCUYu8anV+rT0Pq2X/DT02mWBcD1O2WVkC2DRtWQnse6Tt1G11qHBxdrQEzfTn14dq6+ls/opEFkCapsEWcdzfbSUcpaXqfeXisjDW5XtzRISmO4SLwmryNYDVqZeC48endYz78uW9+pqLRvZUtDmecvDyEb3yXqC+jqi6/ViWjq9xHjb+ux9YOJ9yLQ+9KY+k5kP0SpTPvyj/mQ++BpS95deDeB1AB4hIv+PZ7wXANvGTc3Ul9Gz/Ciu5fWtpWP1eO0xUHmelNWxP7bcbMEr83B7cGBg8sY6O6ZR2ZZ4z1IP1JYq32u7SVkCYIXvL/1Hnv3eLCGXANfUclM/0bxJFE2oVt+8enoC1bavEWRa8GH1s+0TPdcYxbrYdgwb6/HiP3rcIl1NM53teyv+FS1pozFhO/97y7b6v7Qs6c1lZW8AxiQCwFRw9XwKtmDV0w9bJutBZPtndR78oj+25GOfrBZEFTr1j/3DDVvOTvwIKnPhw3TehJ8CAgvIHqgtAaRtgCzrYXXWeQnG/aWe7MUS0spUWGTr3FT7Xv6Ua2gBbqp31oKYB7TW9ojWn21b94ktGTM6XZaNA6s7M86RTUuWeHaW8nQ2AJzUfV5S9hJgvbIE8DJxlzl9yZZjgWktLJDP2mJlI5BEEPMC+1lPzgOX7ZPt95QPjMyzsCmobfqDd+oH6FKyAqxDNn0zWDtTP2mtZD9Be4PVrX5k37qx8r3eWAQr1h47Zq+fQa0FugxMWlCbGnSPpPW8bQJ8S8lBAGyvYmBzBmDuJ/eUPvQ8bJl4Wk97HiSjSdGClc1jbzOr6JhXDb7b/8eoj63Npra/U+JXLVmijt6yc9rZRD1z2j+IIP7Oe2C78CmzLde8Z4nRC6vsp3mkiwA35W2lrc/rZ3SNkWzLK9KyC/GpbT2vrN5te2A7D7Be2Ra0smV74ilzZIlJFgEl83B6m1RtPZk+tuAaXUe2vt5yvbJrz+Km5SAAtldLSGCzN2SbN/ug+9AzoVtemfbAgGN/csY72j1TWp/t/7aXTNtaVu5S3b392LZ8x3lgkewq/DbZr00saTLemS0zpf4p0rreg4jTfLfI6oGtssoqeymbAlRLvqsApr+iskuySff/0KFDi3gd7NchbL5NT72uTY/HKpuR9atECdkkhOZMnKX6tS3ItoDUstXfcWTA0tsorE0rPUc2Cai5z8emZBfiX8DBxMD2DmAt2QWQ6LJLeUA9bbYeaK9PHqiYTrdTfzhQ29k/268pk25u+SlldwFau9CHjKwAW1iWhNmm2vE8oUybVaZC0gJBe1YaXlYH8DdfngfWAlpr+emNRcvbWgp4Xp1T+rRUO7tW90HFwHY+ILDUQ6gfrB449ORFtj0PfgSGbHv6V0t1Hqsr0tklXv3T/5D20KFDx/21ANZaWtp+bANWXh37AJNt9TeS9S1kh+xirCgrPR5Tj1fmlbftejoNEOuBsfa1Z+a1G4Er65WxOtn1aWl9YGVgZccp28ZSS76efu+CrEvIDUm0TJuz9Mu2mekLEw26alt1Nt1qO6OzS0Z7nfaa7T/NYNea/dP1a6+L6Wx/pnrXPbDK1OHZ9LQ9R6Ze+1KyvoVMylyvpFUnEwaT3r4sATWvTD22vCzPLuN1eZOy1wPr9cYsUFpw0Dr9T0KY7RIxq6nPYA9QvD4v5e3NlXUf2ALSAwLP1gMVk01BrU7i6I1gVmyZLMx0eV22lHKLrf4qkLcvjIGqFSOrbXn11fyMzua3xsprz15Ljyzl+UytZ9OeV5UVYIF4k6S1NJwKsp76MgBsQS2z5LBv/loQ8rysKjrf9jvqVwWZ1y/Wv54/XUZDqbWk1P3zpAdMUya+LcM8wG29Pd0WuKqsAHOkx/PogdectnvA2Ipl9QAy034LZvYlgm0/8+D3eGC63ha4av+julr5rN2WHavPE69uDaspwJv6UmDboPJkBVhCpkCJTcopdbTK90DN6ixk9GSNdCzdWjJqWHl16fLRK/Fq6wGsppl3pT0sdm69L1v/FO+sBTumY2CaEofyQJNJL1Ef0y21b62GFrYtewUwz1OZsy1hjrfWglp94Hu8p16JHlCbF8HKwjHTLgNZ1JesB+Z5OBZaTDzvLBsza8XRWuLdjymenme7NPCWkiWeaRG5LYA/BXAbDHy6uJTyHM9+rwBWJQOhrDekIcMmTO8Sz/N0WJ1TdDXNtlPo/mgdy2e2GYhpcNmxsFsydLoFMgA4fPgwBYmFSgtqnq3tF+trJNYuAm9U96Y8Ky2b2KPWkoU+lP8GwCNKKX8lIrcC8Gci8kellPcx470BWNaTsV6PBoGeqL1vF235qo/iW739btXnAVXX0XqjyLyw+rAziGlgWY9LA9Z7waDTDFo98GpBLbK1/dDlMn2MQJiFVAayUZueLAG8JWQJgJWhkr8aT281/rkV7/xXiYDpN6L1AMy9wdlP3zq5Mjpd1n7CR9cU1W/zM2l2bkERfZ0osrV1MfCw+iM4tcbH6lsbYu24RWOd0UXteu0w6fWstgGuKl6s1H74tUREDovIhwBcD+CdpZRLPdudB1jmhs2Bj/epZ2288i1d1LbXH2vjeQl6gmuxUIqAwNK2DV2XBZIHrcjWgqi2Ya+nlW4BzuoZ1Dxd68Mkc59Ym57Oy48+3DJtsXq98nMkA68RYKeIyGXq7wJS102llAcAOB3Ag0Xk/l67e7OE1CJyfPzKbkvQNq1AM6vfa6tXx+Cj7dh2imipyq7H1hVdB9MDx7+t1OnDhw/f8pbJji2AcHzZRImC57pNm1fT0b1i/dAAYuCPJnP0zGTts+MyFUytvnnppd5AVkm+SDtaSjkrY1hK+bKIXALgHAAfZTazrkBEThKRi0XkEyJyhYg8VEROFpF3isinxuNdRlsRkReKyJUi8mEReVCifpruLaMfjNZbplabvcsMpsu2r/tur8VOaGvDlobVA6r6w4cPH1NW2x0+fPi4ZV/VWb1dPjKvTNdry+q2tE0twyDXio2x8YrGmy2XPR0b64yO3SfbH3vvI51XJ1vOToFgryyxhBSR7xGRk8b07QA8CsAnPPu5CH4BgD8upfwggB8GcAWACwG8q5RybwDvGs8B4NEA7j3+XQDgxZkGNv0J5T1kXvzH9qVHF02g6GGPJpS17Y11eRCz0LITWMOs9Xf48GFaDwOcPffiba20rk+PKYvFeffO3hfv3rE8pmPhkAyQ2H1bGoJLyEIxsFMBvEdEPgzg/RhiYG/zjCcvIUXkzgB+DMCTx85/E8A3ReQ8AA8fzV4B4BIAzwJwHoBXjm8Z3ieD93ZqKeW6CW27b8OqTuvn7PXK9sfTsTZt3+ySEfDfhEblbbu2HpbWE8NbQlZ7q6/H1nYVLWwSVr0HHxbra018CyrWJwsWBg2vjPchZduJdBFovbay0hqfpaUnSN+o58MAHpi1n+OB3QvAFwC8XEQ+KCIvEZE7ALh7hdJ4vNtofxqAa1T5I6PuGBGRC2QM8N1www1af1wHsp8u3ica+/TN2GU/2VvLEnYN9hM3mmy2Xq9d1ndtx4Lp1WOyfbGeF+uLHUvtidnr8paQzPMCcEy/dB9aS0dbF7ON7qcd++hZa+W1JLJrPaOePjt/5shSbyF7ZA7ATgDwIAAvLqU8EMDX8O3lIhM2WsddUSnlolLKWaWUs0488cShkxtwnZfUZR4E76HzoGivz5t0nq23ZGzBzpazILPlo6VkXToyENl4WNVlzqM0K9cClR3P6N56oGM6D35RWxmd178pgFwSYvsGsCMAjqg9GhdjANrnReRUABiP1yv7M1T50wFc22qkBQ6dZp+Q7IGYa5d54KLJ0Pokz8Auo89ATAPHg5bWeV4l+2OT2HpYtn4PXtbzYjBl5x5UovvF7k9U3t5DT5iNbatl34IYq489rxb6S8jNN9/c/FtaJgOslPKXAK4RkfuMqkcC+DiAtwI4f9SdD+AtY/qtAH5eBjkbwA1T419Llmk9ED11eA9+TesHiLUZLUNtHZmlpD33AGeXkBZMtn86KJ/985aPLc9M2+i+smvVfbfX4U1idt8ZqJhdT3mWx+r1ynnXwJ7ZyG5T0rEPbFGZuw/slwG8WkRuDeAqAE/BAMU3iMhTAXwWwONH27cDOBfAlQC+Pto2xd4Ets/Le0h0oNvqovqifVr6gYp+a6vVVi2v+61fNliwRfu7rM6e6/K23+wcwDF7zuo+sKpnbbCH05s0bNml9QxW7NxOdgs+DwwRMHo9La+8ts14WVHeJnSbANsmANWSWQArpXwIANuU9khiWwD80tS27CQGjoeGtbNQ0jo9cdkbTa9cL5hYW/ZBYrBqfbICw4S96aabjmtXbzy146Jh7Z3XPgM47lo0zKrYN5b2fnj91/kWAkxn4ZQBz5QlJeujtY3ibLa81es6rI71JwL3FDvbp6Vk7wC2LWmBJAscZldtPXjZh8Hb/hDVy85t+dZ1eh4b09uxq5Lxvtg3AIDjt0/o66x7yVr3UIu3/GJelz0uDS/dJw9K1tbru7X3+uCNC6t3adEfKkvKCjAidrJonTfhe+xa0PP2aTEwZfZqtfpZH/rMb3XVc22v81uemD3X12FBZj2vKQFZD1o1LwMzBqOWh2TLMH0LdrpcFI/KgC4CZKveVntT7JYQ+5xtS3YeYIAfB/PAw3QWMi0wsTqzfcwuGT0vTNtanT7Xddt6WP+qtOJewPHff9RjovMzwq5J96XqbX8y8OqBlC2j+8PKerE6W7/tc+bIrtFri40ls8nqNiWrB0ZETxoGBgaqaGnngckDXs3LeEUWWHNgxeAK+HEv2xctFkb6OltxL91/nWf73yNs8np6Dzj2O5UWOi14ZfTZ+u149AKWlY3A7fWL5dk6vfFcQlaAGbE3zAMOg48tF91Q+2sQ3tGW9eoA+FtKdl3WNoJmFQ9uNs/CjNXH4BZ5XzXexR5WC1Mr3qSJgJaBTQQXL3bWAlIWai1bdmTeWgQ6b+zsODIYRaBaEl7ACjAqHjyynhXL67FhUGzBzdrrIwu6M1gxe93XaMmYzdN9j+AGHP+mkY2hF8z3+sHGp+bZicz0Lbi0oKfL6LQX4/K2Q3htetcX6TNj1AKcB0Gb32q/V1aAOaIn25RlZK3DWyLqdjLwidpj9rYuCyX2qRp9urL+RN5WKcduJqw6Oz4aSq3tE1G8jUlrO0W1YZMr8sRYvv6zeV45Bq2oHqa319ZTDwNPVI8dHzue3jOsZWl4rQAjoieVTnt5FkKsLnv0tiiwcvXcPhjWnh1bb0S9pWG0HJ3qidV84Pi4lo2HseuIlpJaIhDrPrAxrfnRJF7KK4v6o/vu3Vuv7mgMskcmXt+iPnrxtKVkfQvpSB1wbynHbhgDUyu+Zetg4PFgUj9da3vME2S29lMzoz906NAxr62tt9XawGr/WPCeLYurDfukz4rniUUQYUCqdtYminnZPM878/QRBO31tPofAdfrfwSoHghuAl7AuoSkYieTt4z0tkzoeqKbzOATPQweUFlb2fiWp6/AAvh/DtJpDbhoyaj7XP+i4H09Zj0vKwx6dgIxcLHzXq8ss9zMvjHsgZrW6zw2Bq1r9o7R0tzrL6t/CVkB5gi7kTov88Yw+5YxY2+BpIHX8/Yxq9fnU5eTNt+7ZsAP3rOxrdfvSeuaar8yE1rbZuGVzcu0x/qn09F1RMs31k82ZlHbHuCiepaUNQbmSAtQkQcGxIH3Wkc9ektOa8f6xvL0MRPf0nq2i57VZb0tgEPH88Z0PktnduD3Tojo7Vo9snHyJm4EKLaktHUxj82rL9JHYG3Zedcf1Zkdx+wYz5UVYI4w+GSWkZnAOwOjtWf1eV6YztNt2T7rMp7nxDzJKl4Z/ekdBVVtkD7zwQDEO/D1cpZJBHjv6MXDIsBpSLG8DIxaS03dp6if2WvogRIb0ymgW1rWID6RKWCytgx2nr3Vs6MFj86r6Ux8y0tXsZBpeVu6nPfCwQbwo3+Zpsektqd1VTTc7L2zkoGYvnY20TOgYfktz4vZRe237L1nNHse1Rd5gWzsWb4uN1fWJSQRPcitWJS3hGQ3knkaDDAMbGxS6/J2gjP4Mb1tW5f3vK0oz9bpwcR6VlHMi127vQZPWhNK97fqo4lebbPw6snLlrHX493T6Hq0fc+SsGVXjxm4LiUrwBzJfsJkAu+6rOfRRZ6VPc8G1e1Dqr0qBi1bBwNR9bTqNWQ3rmobm7aAYl4k88IyEkFW508Bly3nbYmw5TNemadvASLrmUXgbIGnBV3PNrofU2UFGJEpYGJQ0vV5N5JNTJvHHozMUjLS6zzvJ3CiJaO28zy1CGQMaPU4dwc+66PuV+vIwKXzsqDJwst7ERABqjeo3+qXLavHJLrG7Jiy+peQJQAmImcAeCWA7wVwM4CLSikv8Oz3AmAtiGlb5klY2DHA2eWRhhKDYWY5xQDH9N5DZPX1wa2/RsHEi3tpYctFOw5REN9ec0a8D4bWUV931XuTdttLSttfW1/U3wg8zLZlwwTS7rcAABxwSURBVI7ReLBxnisLeWA3AvgnpZQPiMidAFwuIu8spXycGe88wIDYa/Ig5OXb+jzgsbZZvTXdWgp6ZVk5gHtiLK9el7dktO3b5aJdKjJ41XGpssQSsjWmgA8ufa7tPIBkwJbxvOybzSnLyh54Rtdqx6QFxei4hHjP6oR6rgNQ/6/sV0XkCgz/P3Y/AcYmlD162xNYYD/zRrLWEW2ViIDH0t6SUedFY8AkE8AHjv0HHXpMddraenb22jPigZzlLREP64FDj+dl22T9Y+Wi+hh8PXvbbnTsfSGwhCSfh1NE5DJ1flEp5SJmKCJnYvgv3ZeyfGAPAAb0Qcyzr3pdJ5tI7EHw4ls2Pwro6z56WyY8b6tnyaivv/5ZeHpxLy/mZa8Z6PfCIttosnkTzpv4vfDKBu1rH70YGstv/dk+t2yz9llbPfZLSBJgR0sp7B8BHSMickcAfwjg6aWUr3h2Ow0w70FmRxuHYvkWOiyPwcfWafPtwxDtuJ8KsZ63jF5c0Fsu2nx9ZDGvqYF8O1la95TdiyjYbeHD0rYOVp792qsttwS8svYZWz1O0UsFO55LylJvIUXkVhjg9epSypsi250GGJD7KlDrXB89j03nWZ3n5dgy3pLWlukN3rOxaOVrOOl67QsKbesddVmgP5DvjYOXjsCl+2zPtd0UEET5c+qNIGOvNxoDL88bj1ZZ3Ye5Yp+1qSJDh14K4IpSyu+07HceYNFNsAH4Hs+KBfSjtlpvEqN0FW+5qe2st+XVYfvqeWM6z3uJEf36BBtLdt6SDMSsjX2Tp9MeEJhdBjJT8zL5HsiytlO9r6gd777MkYU8sIcB+DkAHxGRD426Xy+lvJ0Z7zzAgGMnvucpAMfGmdjki4L/kb2WaGJ79t555FHZpWaFmbZlS0Y2ZhZO1r7n1yfsudZZ8SZHNIGWiIe1JnYPUKK8XhjpvrByvTqbx8a2VXZJWegt5J8BSHds5wHGbojWe/Bgae/GeZ9KbHLZ+FXkdbEAvLXxPDHbXl362WP0XUcNIOs96jiXtm39+oQdk4wnFuXruFgLWrauuV5XK7+1taJVPqozu+TsjZOxcWDjaa9jCVkqBtYjewEwb7Kyo43xtAL0UXyLLRuZfS/EIjBWoOg2srvrWb5+E1nrYuXrWNmjF+9ib2Yj8QL4Ot066nq8yZmZzBEcooA8g1cPwDYV5I/qZmPAxmuuLBUD65W9AJieZHbisaMtC8R7uDzgeV6dhVTk/TH4VlB5npi20RPfvoXUwgL4uj8MZN7Dy+CmxwQ4/pcnbH+iiRHBy9NNjYcxe2ajx3kTnpe+Ng8sveCxY+zZs7Fk+rmyAsyIvWlTvLDsBKnnLHZky9lzL8Bf81h8Sed5+8isXfR2sxXA13Y2Hb2N1Q8lWy6ymFg0Zlbnpet1a70HIwsVnW8n9JQlZRZekRdkvbUl3mpm6mrZLikrwIh4APKC+MxWH5k94Ae9WV+0fdSmLRsBSESOC9oz8eJe1gbwA/K6XRv38t5w6uuy3l1WWh8Iuu81n91bBi6d54FuLjQyNlEZ1v9MP6OxsGNp7RmoWJ1LyBJB/F7ZC4Bp6HjgYGCyyyqdx9KRJxXZ2wfBWyK2PLF6rNds3z6yrRJsrFpxrzpebAluY17RfrYlpBXEt0c7blqfAYJn3/KOMjbszyuTSffAMRoDW7fNW0LWGJgjepA9byvaAqEh48WqPH0LYEC8FcLTtbysKja47+XXMeqNe1l46To8oFXp/bS1Qfzahk23jroub7Jq+9YE10F7zz6qJwsvBlbWX3stLfC2dFHdNm+urAAjoicng4b9FIng4wHJTg7vS9esHV3GCtNrLyv6jiPrj26beWN6rCyI2FJR53sfBDZdz20QPyPZ8fTuYWspZu9Ja2L3bGWIbFtxs9a5hmcWlNn+t2yXlBVgjujBZp5V6+GPYk86v+q059MKzkc775mdltZ3HD1IsVhWBDKW9mCmx9im2XmvZCEGzN/UqvPtZK55bBkaeWNT4NXKz7Q15y0oG4dNQGzvACYivwbgFwEUAB8B8BQApwJ4HYCTAXwAwM+VUr4pIrfB8EuLPwLgvwB4Qinl6kQb9Kg9DDbZPOBV8SaphVo0wazOg5hX1pZrPUxsyWhjD94/6ah98OJeURC/jhE7z0pr7PQ12nw7Ea1Ol4smb7WLJnIPvKbAIgvB1nVk2tVjkxnDubJXABOR0wD8CoD7llK+ISJvAPBEAOcC+N1SyutE5PcAPBXAi8fjl0opPyAiTwTwWwCe0GjDBZiGks1j9lbvbZfQegskBihbf8sT87yxFsQsdKId+AAHGeAH7zXMql2VTQXyGax0unWsdbAJrM8jOw9iU2AD8F+yaJXpBSRrYy4c54r3XG9a5i4hTwBwOxH5FoDbY/glxUcA+Jkx/xUAnosBYOeNaQC4GMCLRERKA9tsolW9ttHH1laJqC7rmXlteee6neiaRNpf1GZg8mx13R7IdNsRxHQ9ug4mrYeWBe9r/VE6glatl4GKTUwvMN8LryXBMqU9PZ4tu2hsonGdI3vlgZVSPici/wrAZwF8A8CfALgcwJdLKTeOZkcw/BwsxuM1Y9kbReQGAHcFcFTXKyIXALgAAE499VQ66DrNYmGed1U/kaKlofXARI4NtrOJxD59IojZbRNevIuJBpS21WBidhrKDJIW2iz2ZaUnmM8mShZiVaK3jzZd7SNgLQGu+kz15k1pc6ktFsx2CdkrgInIXTB4VfcE8GUAbwTwaGJar4qN1HFXXIafl70IAO53v/uVFsBaUIqgVyV7XtvKAst6fD1utt36wDwxDR8bw/KC9xZmtYwdI92OB7Peh9/at87tEtPeU+/ZyIBLl9kEvCK9brMHMj0g64XdErJXAAPwKACfKaV8AQBE5E0A/jaAk0TkhNELOx3AtaP9EQBnADgiIicAOBHAFzMN6ckHxEF3L9+me/OieJtXh+6XB09d1m5tqF5atFRstadtvWP0RpK1ZfviPbjR5PDyvCC+PUbg0jYeyFr2c+DVgkVvOVuGjQEDUo/tXGFhjm3IHIB9FsDZInJ7DEvIRwK4DMB7ADwOw5vI8wG8ZbR/63j+3jH/3Zn4VwtEbGJnbO2vREQAq14XgNATs0tC7zuObOlol5RaPG+s9tMuQTVwov1e2SC+rofJlIlgY2PexIuOup7eyT3H62qV97ZW2HKtvWJT2uq9tiVlrwBWSrlURC7GsFXiRgAfxLD0+3cAXicivznqXjoWeSmAV4nIlRg8rydm29KDbZczWt+Kb9kb5u0lY7ZVl/HEWB3ZrRKsDuaNWZBpW5228NN57AjwFxlRIL9XorHOQAvoA5cuP9fr0nVkwNUDFtbvnjKePbtWO45LyN69hSylPAfAc4z6KgAPJrZ/DeDxvW20gMEeUG/zKSvrgSXaMpGJiVU76x2x3wZrbWTVwv4prS7L0toG8GEGtDexemLzWqDOfMhE0KrHTLqWbYEryvMA0QKMt68sU0/krfUCNLJfSvbKA9uW2AfRTig7Ab1yNq3Po7iUd97jiWlhu+/1EtUTDabaPuD/0qoeF6vr+fUJFvtifc1cP7OJ7o++Tu85aIGr1tEDKmajQWT7tTT0WPuttvQYZuq14zVX9jEGthWpNzz62lD01jADMFYHs8+8ncy+aYyWlBpW1hOzeRZkOt9CjAHfQqn17QP2YdErUflsEL8evcnIAGPPM3CodbXAYP88zyvzBxy/p2zu8jSyX0pWgBHRDwP7GZqe/V5Ttk94gXpdN2vHwqfasP5GWyX0NUUg875CZI/A8Xu9GNC0ne3nErJEEJ/1OQsuprP5tb4MrDJQycTOMuW88yzEmEe6hKwAM2InogWMt4TUD4L3/UdrG+mYTYWUB0vPXsNN61q76r1gvT2PYmSto63LttP7/yCttMY6ghjTMdBUfZRuQczWZ9P2OAderXKZMlkoR+OwhOxdEH8bwgbZPsBR4F7neR6VPrdfvfHK2TyR3M/jeOL9MoW+JvtCwDvX4Aemv4Gs51rmLiHnQMyWzQT1M+f2GVtyi0V2C0Qt17sU1EvNzBtLD7hzZckYmIi8DMBjAFxfSrl/ZLt3AGPLRs8Dq3mRrbWP9K2bzQLrLbGw8raCRA+Hzmfp1v99ZGPTCuRrm8w1ZvQRvKpEQf1s2ju3QJkDrzkxqalloj5r+2h858iCS8g/APAiDL9eE8reAaw+HJEXZYEHHLsBNfM1oOh/Oooc/0Xsmm+XhCwYz4Lztm3rjdXriryuKM1gVsfFjlvkkVWdHeeMMHvvg0dL75tIrcuArLbRCw97zJbPel5enV57WW9v12NgpZQ/FZEzM7Z7CTAgDsCzPCCGGLuR0XLSBvNbvywRXZ8HNdvvzNLRpgH+/x7rkQEtgsomlpBaoreQVjcXZLU9DxI9MOuBVgZeXh3Z9jLXoj2yJSQJsFNE5DJ1flEZvv88SXYaYOxTwg54PY+WkfXce2vJzllfmFivy+ZltkpEbWaC/F5a61g5fQQ40ADupS0hPW8ima4HZhG4rE0WZLaeCDpTwbeJMt74zpUkwI6WUs5aqs2dBhjge2DAscu8aBmpz71lYBSoZ54YE7Z9okKitVXC5mmbOga6Hguh1tIRiLdPsPhXTbOfzOldLngTxbu3WXDZY6QD4h35TBdBQdc3BSrZJR/TzXmruYklZGZ+bEL2GmDWO/Hs7HnLM/KEeVlZyXhjnl7nsW0Stg4Lr9bRK1/TQP9XhVoS3Z8IXlaXgRngg8ueZ/RLvqXsKddbJrM8XlIWDOKnZa8BVqHA4NAK9E/xxGy5KAbGJPonHvaarV7r6pjU/MwufHYE+A8Y2uV4FPdqPbTRJMlALNK1oAX0gYvpPBBOhVfrV1t7g/OeTU9AfylZCmAi8loAD8cQLzsC4DmllJcy270GmD7PvF20cLIAtGUrDKLYlg3qt/5seQsyu3TMBOyj37+vxwy0qtg0g5D10Fri2WXubQtiDFo6zyuThVmtcw64epeLc4AWwYyll5KlAFZKeVLW9jsGYNlzq8u8Lax98Dy4KeItBWt7ngcWpdnv30flM3XqOmx/5kh0n1ppBjbA3+fEINU6t8/IpuDVA6Jse9n8JYWtJLYhOw0w9qBGDz4LtrcABvTt79JeGdsrpttgS7usN8bK6fMoXfvDlphVb22iJaSn03lMWpOkF2LsvrF8O1mZbg64WJkeeE3ddtHSsfYy50vJCjAi2beLVryHntWpddlPpgoz5vVUmGjgeaLBxXbJa7uMt8TiXZmfz7H1ANzjYtfS82me+UCJPrCA5cFl097WBw9k3pKVxZqybw8zgMzAMtPOUrK+hSRiB7oVnNe6+uB4cSwb42IB+qxk3lBquLF4l23X2utzlgZy//dRQ8hCs0qvF9YjGYhViTa2RsdekOm25oCl1tMLoAhwrfp0uWzbwLdfKCwlqwdGpN4Uuxvd2kRlmI1XPgM/T1obTrM3mG241ZDy0ra91hE4/qeivY2+Vtf7sGYnCgOWTrP76QGL5bF0bTcLKy+P1ZP9m1p2Sjk9zksBbI2BEbGfTvWNYSvOxbZXRB5StMWinjPPif1VOHi/KqH77HliFjL2Wud4YPWavNiX3rTK+h0BLiMs5hJ9IHnAah0zutqfCExMx2yAb//ckH5mmT2DZa/nxTy2zFYKXWZX30L2yE4DDDj2AfQ2rTKoVR0Q/ycha69hMuct49StEhZOUZyNQczCzDtakLG0vXYLuKnCxpQBykt7UMsADYi3WWTAZetc8i1lNsA/pVwEtSVkBRgR+zBGwXZP17OcrKK9vik3WYNrDgg1kLw+MXhFdWm7KA34WyeWWkJafRZeTBdBDDgeXDrtQYvpbJ1LwWvT5aK3qkvIGsQn4j2I3i56L1gPHO+J2SC+lXrD2ZIw88f6y+qo1+d5YTrfpj2vDMh5XlZnIcUecE+fkcwHTxZirWMVuz8sSmd0us4MaLy6WrvyGXhs21O2W7A658oaA3Mkeii9gLlXT2+ZTHsZ0eDyvCfr6TCw2TpL6f+/j1GszcLNnuu2rWRs2LhkzyNIeR9yNq8Frsx5dotFC2rbLMv6a8dhCVkBZsTeOBbnan19yOoZiFiQPqojuukaOJ43Bhz7G1+snAWXtmU2Pb+6Wo8MUFkvzJZrjUk2j4HJS7MPNZvPwDcFZNveYtEK9Hv1sHLM01vaAwNWgFFpbWTthZie+NGa3XvzqMu2YKX7bG3YstLaelBjNoDvOXlvMasNS7NzrWf3oiWe/RSIAe09Yr3w0mn7AdcLqwiAOgjP6m+Bb0l4rQDbgkQPsafPbCyN6mtJyxuz8GH5FoYMZLY+ZmNtrfT8I1uAAyrrbfVIBC6vnd6Nrb0QY+Cy+T0g0/VM+dPlW9sqpra7lKwAM1JvTOvnbrwfHNReVOuHCi1MMvDLBOft9dj8CGTWnukZxNix5rN/jWavlYHLe9AzD200SaK83k2tvUBj6dpuBCmm8+qbA6/slgoPetlg/hLSWtFsSnYaYIAfaPQe/F494P88joaZhprWWfh4bUeB+CqZX6jQZazO1hfl63T0M9KtT+ilPsHtRGLA0ukW0HohpvuQgZWn1wCJbJaAV9R2j/1SsnpgROrN9LyrjCem7XsC9Bpm+qjTrLwGFgvEM69K27ElX9YD02Cy+qrTeTZdz+2G1aUfzsyHUhZiPUcGQG+p2Dpnebq+TQEo2s+V9byqbklZAeZI9GkRBfFF4p/H0X+tn8fx+sVg1LNVgsEN+PabRv3WUttZULVgVY82j6UtzGq7nngPbmYcI2jp8whgTJeBFsvvgZctv1SwPwssWzYTsLfwWhJiK8CIZLcuTCln7avnob20CkELKy/OVesCjt8qofvLYOZdmwUZuyYGtigvSgPtQL6tv0e8/nvnrXT2CMTg8tItXa03gssUePUE4bObYll7S0g0HzYpOw0wfSMzHlXkifUGGbVnZ5eLrJ8MbtGysudcp+3ysrYP9H33sbWEtA82082RJSDGANWCVj32wMs7r3X3wqoFrp6/njeTXt5SsgKMiL7Jcz2x+jf353F0e61PHhaYr+VsPey8phnQou0RrKzVARxu9lzrrL5HonHMnmehBfjeFtO1IMbAxWx6YFbr2QS8esotJetbSCLWE8rGttiOfRaMj/5qXEwDqLWE9Gy8n7vu8cAiHfPMdBsesFianVddrXOOsPIZaEVpgHta3nFq2gMX00U2ta4WaJhdq2xv3lKyemBE7CBnY1vs4e79LqNeOkblLXy8/Gw/tL0FFdO1YGYnfU/sy/PCqrQe2t77ZHURsIBpu/FZXitd22oBy9N78NHn+npabxp7wRXlLyE7GwMTkZcBeAyA60sp9x91JwN4PYAzAVwN4KdLKV+SYTReAOBcAF8H8ORSygfGMucD+Gdjtb9ZSnlFou1bBt77wUEvtmW9LO97kD0SxbRY320+g5HuzxwPLIJZrdu2V/tUJeOF6TxbviWerdVHdVovS6d7jpm0brMFKaZj9S29xaIFvCh/ySA+sJwHJiLnYODIYQAvKaU8z7PNeGB/AOBFAF6pdBcCeFcp5XkicuF4/iwAjwZw7/HvIQBeDOAhI/CeA+AsAAXA5SLy1lLKlxIXA+D4QD3bfJr5bqOGnoVM5s+Wr31ktizP6tj/dMxADJi2fcICqkr2VzrmLiOz5byNrRG4mI5BpAUv3X4EKXse6SLvR4OGwafa1Q+jLAQz8No1gInIYQD/F4C/C+AIgPePrPg4s28CrJTypyJyplGfh+E/5wLAKwBcggFg5wF4ZRmu5H0icpKInDravrOU8sWxk+8EcA6A1yYuyD23HlUGZF7ZXrH7s1i/rXfGdKw+DTJdjkGM6Wx7zN6m2VeM2PUt+cADfB8SA1Im3XPMgkunsxBjdWaAw4A3pbwe0+wesiVkoSD+gwFcWUq5CgBE5HUYuDINYI7cvZRyHQCUUq4TkbuN+tMAXKPsjow6T3+ciMgFAC4YT//m8OHDH53Yx4OQUwAcPehOJGWf+grsV3/3qa8AcJ8F6ngHhutuyW1F5DJ1flEp5SJ1zljxEK+ypYP4DOcl0B+vHC7mIgAQkctKKWct173Nyj71d5/6CuxXf/epr8DQ37l1lFLOWaIv6GAFAEz9HsHnx6UhxuP1o/4IgDOU3ekArg30q6yyyipaulgxFWBvBXD+mD4fwFuU/udlkLMB3DAuNd8B4CdE5C4ichcAPzHqVllllVW0vB/AvUXkniJyawBPxMAVKpltFK/FEIQ/RUSOYHib+DwAbxCRpwL4LIDHj+Zvx7CF4koM2yieAgCllC+KyP86dg4AfqMG9BtyUdtkp2Sf+rtPfQX2q7/71Fdgh/pbSrlRRJ6GwcE5DOBlpZSPefZyEJvPVllllVWWkGV/EGiVVVZZZYuyAmyVVVbZW9lZgInIOSLySRG5Uobd/gfdnzNE5D0icoWIfExEfnXUnywi7xSRT43Hu4x6EZEXjv3/sIg86AD6fFhEPigibxvP7ykil459ff0YJIWI3GY8v3LMP/MA+nqSiFwsIp8Yx/ihOz62vzY+Bx8VkdeKyG13ZXxF5GUicr2IfFTpusdSRM4f7T8lw1cBd096v0qzjT8MwbtPA7gXgFsD+E8A7nvAfToVwIPG9J0A/GcA9wXw2wAuHPUXAvitMX0ugD/CsK/lbACXHkCfnwHgNQDeNp6/AcATx/TvAfgfx/Q/BvB7Y/qJAF5/AH19BYBfHNO3BnDSro4ths2WnwFwOzWuT96V8QXwYwAeBOCjStc1lgBOBnDVeLzLmL7Ltp+L5rUedAecG/BQAO9Q588G8OyD7pfp41swfF/rkwBOHXWnAvjkmP59AE9S9rfYbal/pwN4F4BHAHjb+IAeBXCCHWMMb3weOqZPGO1ki3298wgEMfpdHdu6W/zkcbzeBuDv7dL4YvihBQ2wrrEE8CQAv6/0x9jtyt+uLiHTXz06CBmXAA8EcCnM16oAtL5WtS15PoBnAqhfULsrgC+XUm4k/bmlr2P+DaP9tuReAL4A4OXjkvclInIH7OjYllI+B+BfYdhCdB2G8bocuzu+QP9YHvTzm5JdBVjX1wm2KSJyRwB/CODppZSvRKZEt5VrEJH680eXJ/tz0ON9AoYlz4tLKQ8E8DUMyxxPDrS/Y/zoPAD3BHAPAHfA8EssXp8Oenwjmf31v4OUXQXYTn71SERuhQFery6lvGlU936tahvyMACPFZGrAbwOwzLy+QBOEpG6eVn355a+jvknAshsNF5KjgA4Ukq5dDy/GAPQdnFsAeBRAD5TSvlCKeVbAN4E4G9jd8cX+A79+t+uAqzr6wTbEBERAC8FcEUp5XdUVu/XqjYupZRnl1JOL6WciWHs3l1K+VkA7wHwOKev9RoeN9pv7dO2lPKXAK4RkfqrCI/E8PMpOze2o3wWwNkicvvxuaj93cnxJX34zvn630EH4YIg5LkY3vR9GsA/3YH+/CgGF/rDAD40/p2LIZbxLgCfGo8nj/aC4YfZPg3gIwDOOqB+Pxzffgt5LwB/juGrXm8EcJtRf9vx/Mox/14H0M8HALhsHN9/g+HN186OLYD/BcAnAHwUwKsA3GZXxhfD7+xdB+BbGDypp04ZSwC/MPb5SgBPOYjnt/W3fpVolVVW2VvZ1SXkKqusskpTVoCtssoqeysrwFZZZZW9lRVgq6yyyt7KCrBVVlllb2UF2CqrrLK3sgJslVVW2Vv5/wFWFDWSXcvk5wAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "plt.title(\"Image plot of $\\sqrt{x^2 + y^2}$ for a grid of values\")\n",
    "plt.imshow(z, cmap=plt.cm.gray); plt.colorbar()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Expressing Conditional Logic as Array Operations"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 158,
   "metadata": {},
   "outputs": [],
   "source": [
    "xarr = np.array([1.1, 1.2, 1.3, 1.4, 1.5])\n",
    "yarr = np.array([2.1, 2.2, 2.3, 2.4, 2.5])\n",
    "cond = np.array([True, False, True, True, False])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 161,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[(1.1, 2.1, True), (1.2, 2.2, False), (1.3, 2.3, True), (1.4, 2.4, True), (1.5, 2.5, False)]\n"
     ]
    }
   ],
   "source": [
    "m=list(zip(xarr, yarr, cond))\n",
    "print(m)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 163,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.1 2.1 True\n",
      "1.2 2.2 False\n",
      "1.3 2.3 True\n",
      "1.4 2.4 True\n",
      "1.5 2.5 False\n"
     ]
    }
   ],
   "source": [
    "for x, y, c in zip(xarr, yarr, cond):\n",
    "    print(x,y,c)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 164,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1.1, 2.2, 1.3, 1.4, 2.5]"
      ]
     },
     "execution_count": 164,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "result = [(x if c else y) #当cond中的值为True时，选取xarr的值，否则从yarr中选取\n",
    "          for x, y, c in zip(xarr, yarr, cond)]\n",
    "result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 165,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1.1, 2.2, 1.3, 1.4, 2.5])"
      ]
     },
     "execution_count": 165,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "result = np.where(cond, xarr, yarr)#1、纯python对大数据组的处理速度不是很快2、使用np.where则可以将该功能写的非常简洁\n",
    "result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 166,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.3136824 ,  1.40103113,  0.82522926,  0.5299917 ],\n",
       "       [ 0.49562133, -0.03287678, -0.61834255,  1.91530718],\n",
       "       [ 0.12544481, -0.72857105, -0.08580418,  0.47777399],\n",
       "       [-1.17553233,  1.24219127,  1.88397072, -0.86973204]])"
      ]
     },
     "execution_count": 166,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.random.randn(4, 4)\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 167,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-2,  2,  2,  2],\n",
       "       [ 2, -2, -2,  2],\n",
       "       [ 2, -2, -2,  2],\n",
       "       [-2,  2,  2, -2]])"
      ]
     },
     "execution_count": 167,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr > 0\n",
    "np.where(arr > 0, 2, -2)#np.where的第二个和第三个参数不必是数组，它们都可以是标量值。将所有正值替换为2，将所有负值替换为-2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 168,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.3136824 ,  2.        ,  2.        ,  2.        ],\n",
       "       [ 2.        , -0.03287678, -0.61834255,  2.        ],\n",
       "       [ 2.        , -0.72857105, -0.08580418,  2.        ],\n",
       "       [-1.17553233,  2.        ,  2.        , -0.86973204]])"
      ]
     },
     "execution_count": 168,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.where(arr > 0, 2, arr) # set only positive values to 2只将正值设置为2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "result = [ ]\n",
    "for i in range(n):\n",
    "    if cond1[i] and cond2[i]:\n",
    "        result.append(0)\n",
    "    elif cond1[i]:\n",
    "        result.append(1)\n",
    "    elif cond2 [ i] :\n",
    "        result.append(2)\n",
    "    else:\n",
    "        result.append(3)#这个for循环可以被改写成一个嵌套的where表达式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "np.where(cond1 & cond2, 0,\n",
    "    np.where(cond1, 1,\n",
    "        np.where(cond2, 2, 3)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Mathematical and Statistical Methods"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-1.12612097,  1.29942652,  2.20450345, -0.04819269],\n",
       "       [ 0.02997318,  1.06410929, -1.32569772, -0.45834511],\n",
       "       [ 0.47746584, -0.94502139,  0.51635641,  0.40090932],\n",
       "       [ 0.02390962, -0.80755218,  0.21970254,  2.54261163],\n",
       "       [ 0.18627604, -0.6570484 ,  0.52772679, -1.32121618]])"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.random.randn(5, 4)\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.14018879969327164"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.mean()#计算平均值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.14018879969327164"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.mean(arr)#计算平均值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2.8037759938654325"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.sum()#计算和"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0.58240408, -0.17249009,  0.11242754,  0.4946679 , -0.31606544])"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.mean(axis=1)#行"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-0.40849628, -0.04608616,  2.14259147,  1.11576697])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.sum(axis=0)#列"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0,  1,  3,  6, 10, 15, 21, 28], dtype=int32)"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.array([0, 1, 2, 3, 4, 5, 6, 7])\n",
    "arr.cumsum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1, 2],\n",
       "       [3, 4, 5],\n",
       "       [6, 7, 8]])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  1,  2],\n",
       "       [ 3,  5,  7],\n",
       "       [ 9, 12, 15]], dtype=int32)"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.cumsum(axis=0)#元素的累积和"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[  0,   0,   0],\n",
       "       [  3,  12,  60],\n",
       "       [  6,  42, 336]], dtype=int32)"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.cumprod(axis=1)#元素的累积积"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Methods for Boolean Arrays"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "53"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.random.randn(100)\n",
    "(arr > 0).sum()#对布尔型数组中的True值计数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bools = np.array([False, False, True, False])\n",
    "bools.any()#any用于测试数组中是否存在一个或多个True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bools.all()#all则检查数组中所有值是否都是True（非布尔数组，所有非0元素将会被当做True）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Sorting"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0.2891493 ,  0.58384528,  1.86049145, -0.91786076,  0.31375091,\n",
       "        1.05465959])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.random.randn(6)\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-0.91786076,  0.2891493 ,  0.31375091,  0.58384528,  1.05465959,\n",
       "        1.86049145])"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.sort()\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.39533253, -0.1846872 , -0.0627409 ],\n",
       "       [-1.78514794, -0.84673196,  0.59642979],\n",
       "       [-0.02564199,  0.7769619 ,  1.54845699],\n",
       "       [ 0.81230757, -0.18601718,  0.30938775],\n",
       "       [-0.37459304,  1.31521325, -1.63270718]])"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.random.randn(5, 3)\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.39533253, -0.1846872 , -0.0627409 ],\n",
       "       [-1.78514794, -0.84673196,  0.59642979],\n",
       "       [-0.02564199,  0.7769619 ,  1.54845699],\n",
       "       [-0.18601718,  0.30938775,  0.81230757],\n",
       "       [-1.63270718, -0.37459304,  1.31521325]])"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.sort(1)#按轴进行排序\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "large_arr = np.random.randn(1000)\n",
    "large_arr.sort()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-1.691788003322647"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "large_arr[int(0.05 * len(large_arr))] # 5% quantile计算数组分位数最简单的办法是对其进行排序，然后选取特定位置的值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Unique and Other Set Logic"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['Bob', 'Joe', 'Will'], dtype='<U4')"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])\n",
    "np.unique(names)#用于找出数组中的唯一值并返回已排序的结果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2, 3, 4])"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ints = np.array([3, 3, 3, 2, 2, 1, 1, 4, 4])\n",
    "np.unique(ints)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['Bob', 'Joe', 'Will']"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sorted(set(names))#跟np.unique等价的纯python代码"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ True, False, False,  True,  True, False,  True])"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "values = np.array([6, 0, 0, 3, 2, 5, 6])\n",
    "np.in1d(values, [2, 3, 6])#np.in1d用于测试一个数组在另一个数组中的成员资格，返回一个布尔型数组"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## File Input and Output with Arrays"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "arr = np.arange(10)\n",
    "np.save('some_array', arr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.load('some_array.npy')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "np.savez('array_archive.npz', a=arr, b=arr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arch = np.load('array_archive.npz')\n",
    "arch['b']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "arr1 = np.loadtxt('array_ex.txt',delimiter = ',')#以逗号为分割符"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.580052,  0.18673 ,  1.040717,  1.134411],\n",
       "       [ 0.194163, -0.636917, -0.938659,  0.124094],\n",
       "       [-0.12641 ,  0.268607, -0.695724,  0.047428],\n",
       "       [-1.484413,  0.004176, -0.744203,  0.005487],\n",
       "       [ 2.302869,  0.200131,  1.670238, -1.88109 ],\n",
       "       [-0.19323 ,  1.047233,  0.482803,  0.960334]])"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Linear Algebra"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 28.,  64.],\n",
       "       [ 67., 181.]])"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = np.array([[1., 2., 3.], [4., 5., 6.]])\n",
    "y = np.array([[6., 23.], [-1, 7], [8, 9]])\n",
    "x\n",
    "y\n",
    "x.dot(y)#等价于np.dot(x,y)，矩阵乘法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 28.,  64.],\n",
       "       [ 67., 181.]])"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.dot(x, y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 6., 15.])"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.dot(x, np.ones(3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 6., 15.])"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x @ np.ones(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 7.54370466, -1.65412648, -0.26918042, -2.88129478, -3.78507171],\n",
       "       [-1.65412648,  2.05753413, -1.00925318,  1.7486519 ,  2.52191291],\n",
       "       [-0.26918042, -1.00925318,  4.25454413, -2.75119427, -4.48571237],\n",
       "       [-2.88129478,  1.7486519 , -2.75119427,  4.67754507,  3.91943427],\n",
       "       [-3.78507171,  2.52191291, -4.48571237,  3.91943427,  8.08306507]])"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from numpy.linalg import inv, qr\n",
    "X = np.random.randn(5, 5)\n",
    "mat = X.T.dot(X)\n",
    "mat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.94635001, -0.47311798,  1.63104457,  0.78436957,  1.11557642],\n",
       "       [-0.47311798,  1.2172863 , -1.1130234 , -0.63956626, -0.9088929 ],\n",
       "       [ 1.63104457, -1.1130234 ,  3.50907863,  1.55300676,  2.30536041],\n",
       "       [ 0.78436957, -0.63956626,  1.55300676,  1.09878382,  0.89589235],\n",
       "       [ 1.11557642, -0.9088929 ,  2.30536041,  0.89589235,  1.77463349]])"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "inv(mat)#矩阵的逆"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1.00000000e+00, -5.70384327e-16,  6.06907233e-16,\n",
       "        -1.56517573e-16, -1.92296103e-17],\n",
       "       [-4.87072431e-16,  1.00000000e+00, -1.48349152e-15,\n",
       "        -4.53634506e-16,  1.90423597e-16],\n",
       "       [-5.42761539e-16,  6.79907012e-16,  1.00000000e+00,\n",
       "        -9.44154875e-16,  1.41282452e-16],\n",
       "       [-2.08876084e-15,  6.88601139e-16, -1.74613768e-15,\n",
       "         1.00000000e+00, -2.26004044e-15],\n",
       "       [-1.46730967e-15,  1.76633951e-15, -3.80421964e-15,\n",
       "        -1.51601334e-15,  1.00000000e+00]])"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mat.dot(inv(mat))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [],
   "source": [
    "q, r = qr(mat)#QR分解"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.83131736, -0.44181625,  0.01423839, -0.06111535,  0.33131861],\n",
       "       [ 0.18228498, -0.57651555, -0.74764179,  0.05068386, -0.26993501],\n",
       "       [ 0.02966372,  0.44021553, -0.58005383, -0.0092833 ,  0.68467637],\n",
       "       [ 0.31751911, -0.27500437,  0.13531147, -0.8570004 ,  0.26607394],\n",
       "       [ 0.41711546, -0.45056753,  0.2933554 ,  0.5090778 ,  0.52705408]])"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "q"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-9.07439805,  3.32738268, -2.57860845,  5.75247926,  8.08930643],\n",
       "       [ 0.        , -2.51684838,  5.35140163, -3.99855576, -6.4761243 ],\n",
       "       [ 0.        ,  0.        , -3.40531353,  2.03016322,  3.56412899],\n",
       "       [ 0.        ,  0.        ,  0.        , -1.72310107,  1.15674074],\n",
       "       [ 0.        ,  0.        ,  0.        ,  0.        ,  0.2969932 ]])"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Pseudorandom Number Generation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1.11480832,  0.07251094,  0.99079738,  1.27296548],\n",
       "       [ 0.06206708, -0.52575844,  1.6308453 , -1.57086918],\n",
       "       [ 0.55854319, -0.02864933, -0.81055084,  0.32670746],\n",
       "       [ 1.16787306,  1.77066333,  1.70850178,  0.7310902 ]])"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "samples = np.random.normal(size=(4, 4))\n",
    "samples"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [],
   "source": [
    "nsteps = 1000\n",
    "draws = np.random.randint(0, 2, size=nsteps)\n",
    "steps = np.where(draws > 0, 1, -1)\n",
    "walk = steps.cumsum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-46"
      ]
     },
     "execution_count": 72,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "walk.min()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "walk.max()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "83"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#需要多久才能距离初始0点至少10步远（任一方均可）\n",
    "#np.abs(walk)>=10可以得到一个布尔型数组，它表示的是距离是否达到或超过10\n",
    "#如果想知道的是第一个10或-10的索引，可以用argmax，它返回的是布尔型数组第一个最大值的索引（True就是最大值）\n",
    "(np.abs(walk) >= 10).argmax()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Simulating Many Random Walks at Once"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1, 0, ..., 0, 1, 0],\n",
       "       [0, 1, 0, ..., 1, 1, 0],\n",
       "       [0, 1, 0, ..., 0, 0, 1],\n",
       "       ...,\n",
       "       [0, 0, 0, ..., 0, 1, 0],\n",
       "       [0, 0, 1, ..., 0, 0, 0],\n",
       "       [1, 0, 0, ..., 0, 0, 1]])"
      ]
     },
     "execution_count": 78,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "nwalks = 5000\n",
    "nsteps = 1000\n",
    "draws = np.random.randint(0, 2, size=(nwalks, nsteps))\n",
    "draws"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(5000, 1000)"
      ]
     },
     "execution_count": 79,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "draws.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-1,  1, -1, ..., -1,  1, -1],\n",
       "       [-1,  1, -1, ...,  1,  1, -1],\n",
       "       [-1,  1, -1, ..., -1, -1,  1],\n",
       "       ...,\n",
       "       [-1, -1, -1, ..., -1,  1, -1],\n",
       "       [-1, -1,  1, ..., -1, -1, -1],\n",
       "       [ 1, -1, -1, ..., -1, -1,  1]])"
      ]
     },
     "execution_count": 80,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "steps = np.where(draws > 0, 1, -1)\n",
    "steps"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ -1,   0,  -1, ..., -86, -85, -86],\n",
       "       [ -1,   0,  -1, ..., -46, -45, -46],\n",
       "       [ -1,   0,  -1, ...,  22,  21,  22],\n",
       "       ...,\n",
       "       [ -1,  -2,  -3, ..., -16, -15, -16],\n",
       "       [ -1,  -2,  -1, ...,  14,  13,  12],\n",
       "       [  1,   0,  -1, ...,   0,  -1,   0]], dtype=int32)"
      ]
     },
     "execution_count": 81,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "walks = steps.cumsum(1)#计算每行的累积值\n",
    "walks"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "128"
      ]
     },
     "execution_count": 82,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "walks.max()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-128"
      ]
     },
     "execution_count": 83,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "walks.min()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ True,  True,  True, ..., False, False, False])"
      ]
     },
     "execution_count": 84,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "hits30 = (np.abs(walks) >= 30).any(1)#计算每行是否存在一个或多个True（不是5000个过程都到达了30，用any方法进行检验）\n",
    "hits30"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(5000,)"
      ]
     },
     "execution_count": 85,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "hits30.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3363"
      ]
     },
     "execution_count": 86,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "hits30.sum() #到达30或-30的数量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "499.7772821885222"
      ]
     },
     "execution_count": 87,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "crossing_times = (np.abs(walks[hits30]) >= 30).argmax(1)#利用hits30这个数组选出那些穿越了30（绝对值）的随机漫步（行）\n",
    "                                                         #并调用argmax在轴1上获取穿越时间\n",
    "crossing_times.mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "metadata": {},
   "outputs": [],
   "source": [
    "steps = np.random.normal(loc=0, scale=0.25,size=(4, 4))#生成指定均值和标准差的正态分布数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.12225625,  0.08576666, -0.01584225, -0.33832667],\n",
       "       [ 0.00490628, -0.35086095,  0.43847274,  0.17080446],\n",
       "       [-0.05940681, -0.41643965, -0.07903843,  0.67851493],\n",
       "       [-0.18390939,  0.09275975, -0.07397382,  0.3308022 ]])"
      ]
     },
     "execution_count": 89,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "steps"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Conclusion"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
